guice-3.0/0000755000175000017500000000000011542727760012357 5ustar drazzibdrazzibguice-3.0/compareBuilds.sh0000644000175000017500000000416511534766744015520 0ustar drazzibdrazzib#!/bin/bash # Compares the ant jars to the maven jars and makes sure they're the same # (or different where/how expected) # Build everything first. function cleanAndBuild { mvn clean ant clean.all ant no_aop ant dist test.dist mvn package cd build/no_aop ant dist test.dist cd ../.. } function findAndCompareJars { version=3.0 for ANT in `find -name "*-rc3.jar" -path "./build/dist/*"` do if [ $ANT = "./build/dist/guice-3.0-rc3.jar" ]; then #Check main build MVN=./mvn/guice-$version-rc3.jar extension=core compareJars "$ANT" "$MVN" $extension compareJars "./build/no_aop/build/dist/guice-3.0-rc3-no_aop.jar" "./mvn/guice-$version-rc3-no_aop.jar" "no_aop: $extension" #also compare no_aop core else # Check extensions extension=`echo $ANT | awk -F"-" '{print $2 }'` MVN=./mvn/guice-$extension-$version-rc3.jar compareJars "$ANT" "$MVN" $extension fi done; } function compareJars { ANT=$1 MVN=$2 extension=$3 echo Comparing $3 mkdir tmp$$ cp $ANT tmp$$/ant.jar cp $MVN tmp$$/mvn.jar cd tmp$$ mkdir ant mkdir mvn cd ant jar -xf ../ant.jar cd .. cd mvn jar -xf ../mvn.jar cd .. # ant puts LICENSE & NOTICE files in a different place echo LICENSE > excludes echo NOTICE >> excludes # ant does not create DEPENDENCIES echo DEPENDENCIES >> excludes # ant/mvn slightly different in MANIFEST.MF echo MANIFEST.MF >> excludes # ant leaves empty directories for some jarjar'd paths -- # we grep -v instead of exclude because we want to make sure # if any files in those directories exist, that they're diff'd diff -u --recursive -Xexcludes ant mvn | grep -v "Only in ant/com/google/inject/internal/asm: signature" | grep -v "Only in ant/com/google/inject/internal/cglib: beans" | grep -v "Only in ant/com/google/inject/internal/cglib: transform" | grep -v "Only in ant/com/google/inject/internal/cglib: util" cd .. rm -rf "tmp$$" } #cleanAndBuild echo "Starting to compare jars... Check the output closely!" echo findAndCompareJars echo echo "If the only thing that printed out is 'Comparing ', then you're good!"guice-3.0/extensions/0000755000175000017500000000000011542721074014546 5ustar drazzibdrazzibguice-3.0/extensions/spring/0000755000175000017500000000000011542727750016057 5ustar drazzibdrazzibguice-3.0/extensions/spring/build/0000755000175000017500000000000011542727752017160 5ustar drazzibdrazzibguice-3.0/extensions/spring/build/META-INF/0000755000175000017500000000000011542727752020320 5ustar drazzibdrazzibguice-3.0/extensions/spring/build/META-INF/MANIFEST.MF0000644000175000017500000000126111542727750021750 0ustar drazzibdrazzibManifest-Version: 1.0 Export-Package: com.google.inject.spring;version="1.3" Bundle-Name: guice-spring Created-By: 1.6.0_23 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-Copyright: Copyright (C) 2006 Google Inc. Bundle-Vendor: Google, Inc. Fragment-Host: com.google.inject Bundle-Version: 3.0 Bundle-ManifestVersion: 2 Bundle-Description: Guice is a lightweight dependency injection framew ork for Java 5 and above Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-DocURL: http://code.google.com/p/google-guice/ Bundle-SymbolicName: com.google.inject.spring Import-Package: org.springframework.beans.factory guice-3.0/extensions/spring/build/dist/0000755000175000017500000000000011542727750020121 5ustar drazzibdrazzibguice-3.0/extensions/spring/build/classes/0000755000175000017500000000000011542727750020613 5ustar drazzibdrazzibguice-3.0/extensions/spring/build/classes/com/0000755000175000017500000000000011542727750021371 5ustar drazzibdrazzibguice-3.0/extensions/spring/build/classes/com/google/0000755000175000017500000000000011542727750022645 5ustar drazzibdrazzibguice-3.0/extensions/spring/build/classes/com/google/inject/0000755000175000017500000000000011542727750024121 5ustar drazzibdrazzibguice-3.0/extensions/spring/build/classes/com/google/inject/spring/0000755000175000017500000000000011542727750025423 5ustar drazzibdrazzibguice-3.0/extensions/spring/pom.xml0000644000175000017500000000143411464433216017370 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-spring Google Guice - Extensions - Spring org.springframework spring-beans 3.0.5.RELEASE provided guice-3.0/extensions/spring/build.xml0000644000175000017500000000124111461503370017664 0ustar drazzibdrazzib guice-3.0/extensions/spring/spring.iml0000644000175000017500000000301211434007576020055 0ustar drazzibdrazzib guice-3.0/extensions/spring/build.properties0000644000175000017500000000023111461376774021276 0ustar drazzibdrazziblib.dir=../../lib src.dir=src test.dir=test build.dir=build test.class=com.google.inject.spring.SpringTest module=com.google.inject.spring fragment=true guice-3.0/extensions/spring/test/0000755000175000017500000000000011434007600017017 5ustar drazzibdrazzibguice-3.0/extensions/spring/test/com/0000755000175000017500000000000011434007600017575 5ustar drazzibdrazzibguice-3.0/extensions/spring/test/com/google/0000755000175000017500000000000011434007600021051 5ustar drazzibdrazzibguice-3.0/extensions/spring/test/com/google/inject/0000755000175000017500000000000011434007600022325 5ustar drazzibdrazzibguice-3.0/extensions/spring/test/com/google/inject/spring/0000755000175000017500000000000011434007600023627 5ustar drazzibdrazzibguice-3.0/extensions/spring/test/com/google/inject/spring/SpringIntegrationTest.java0000644000175000017500000000703111434007600031001 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spring; import com.google.inject.AbstractModule; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.name.Names; import static com.google.inject.spring.SpringIntegration.fromSpring; import junit.framework.TestCase; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; /** * @author crazybob@google.com (Bob Lee) */ public class SpringIntegrationTest extends TestCase { public void testBindFromSpring() throws CreationException { final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); RootBeanDefinition singleton = new RootBeanDefinition(Singleton.class); beanFactory.registerBeanDefinition("singleton", singleton); RootBeanDefinition prototype = new RootBeanDefinition(Prototype.class, false); beanFactory.registerBeanDefinition("prototype", prototype); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(BeanFactory.class).toInstance(beanFactory); bind(Singleton.class) .toProvider(fromSpring(Singleton.class, "singleton")); bind(Prototype.class) .toProvider(fromSpring(Prototype.class, "prototype")); } }); assertNotNull(injector.getInstance(Singleton.class)); assertSame(injector.getInstance(Singleton.class), injector.getInstance(Singleton.class)); assertNotNull(injector.getInstance(Prototype.class)); assertNotSame(injector.getInstance(Prototype.class), injector.getInstance(Prototype.class)); } public void testBindAll() throws CreationException { final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); RootBeanDefinition singleton = new RootBeanDefinition(Singleton.class); beanFactory.registerBeanDefinition("singleton", singleton); RootBeanDefinition prototype = new RootBeanDefinition(Prototype.class, false); beanFactory.registerBeanDefinition("prototype", prototype); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { SpringIntegration.bindAll(binder(), beanFactory); } }); Key singletonKey = Key.get(Singleton.class, Names.named("singleton")); Key prototypeKey = Key.get(Prototype.class, Names.named("prototype")); assertNotNull(injector.getInstance(singletonKey)); assertSame(injector.getInstance(singletonKey), injector.getInstance(singletonKey)); assertNotNull(injector.getInstance(prototypeKey)); assertNotSame(injector.getInstance(prototypeKey), injector.getInstance(prototypeKey)); } static class Singleton {} static class Prototype {} } guice-3.0/extensions/spring/src/0000755000175000017500000000000011434007576016643 5ustar drazzibdrazzibguice-3.0/extensions/spring/src/com/0000755000175000017500000000000011434007576017421 5ustar drazzibdrazzibguice-3.0/extensions/spring/src/com/google/0000755000175000017500000000000011434007576020675 5ustar drazzibdrazzibguice-3.0/extensions/spring/src/com/google/inject/0000755000175000017500000000000011434007576022151 5ustar drazzibdrazzibguice-3.0/extensions/spring/src/com/google/inject/spring/0000755000175000017500000000000011434007600023437 5ustar drazzibdrazzibguice-3.0/extensions/spring/src/com/google/inject/spring/package-info.java0000644000175000017500000000131211461123574026634 0ustar drazzibdrazzib/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Spring integration; this extension requires {@code guice-spring-3.0.jar}. */ package com.google.inject.spring;guice-3.0/extensions/spring/src/com/google/inject/spring/SpringIntegration.java0000644000175000017500000000753311434007576027774 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spring; import com.google.inject.Binder; import com.google.inject.Inject; import com.google.inject.Provider; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.name.Names; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ListableBeanFactory; /** * Integrates Guice with Spring. * * @author crazybob@google.com (Bob Lee) */ public class SpringIntegration { private SpringIntegration() {} /** * Creates a provider which looks up objects from Spring using the given name. * Expects a binding to {@link * org.springframework.beans.factory.BeanFactory}. Example usage: * *
   * bind(DataSource.class)
   *   .toProvider(fromSpring(DataSource.class, "dataSource"));
   * 
*/ public static Provider fromSpring(Class type, String name) { return new InjectableSpringProvider(type, name); } /** * Binds all Spring beans from the given factory by name. For a Spring bean * named "foo", this method creates a binding to the bean's type and * {@code @Named("foo")}. * * @see com.google.inject.name.Named * @see com.google.inject.name.Names#named(String) */ public static void bindAll(Binder binder, ListableBeanFactory beanFactory) { binder = binder.skipSources(SpringIntegration.class); for (String name : beanFactory.getBeanDefinitionNames()) { Class type = beanFactory.getType(name); bindBean(binder, beanFactory, name, type); } } static void bindBean(Binder binder, ListableBeanFactory beanFactory, String name, Class type) { SpringProvider provider = SpringProvider.newInstance(type, name); try { provider.initialize(beanFactory); } catch (Exception e) { binder.addError(e); return; } binder.bind(type) .annotatedWith(Names.named(name)) .toProvider(provider); } static class SpringProvider implements Provider { BeanFactory beanFactory; boolean singleton; final Class type; final String name; public SpringProvider(Class type, String name) { this.type = checkNotNull(type, "type"); this.name = checkNotNull(name, "name"); } static SpringProvider newInstance(Class type, String name) { return new SpringProvider(type, name); } void initialize(BeanFactory beanFactory) { this.beanFactory = beanFactory; if (!beanFactory.isTypeMatch(name, type)) { throw new ClassCastException("Spring bean named '" + name + "' does not implement " + type.getName() + "."); } singleton = beanFactory.isSingleton(name); } public T get() { return singleton ? getSingleton() : type.cast(beanFactory.getBean(name)); } volatile T instance; private T getSingleton() { if (instance == null) { instance = type.cast(beanFactory.getBean(name)); } return instance; } } static class InjectableSpringProvider extends SpringProvider { InjectableSpringProvider(Class type, String name) { super(type, name); } @Inject @Override void initialize(BeanFactory beanFactory) { super.initialize(beanFactory); } } } guice-3.0/extensions/mini/0000755000175000017500000000000011460132762015501 5ustar drazzibdrazzibguice-3.0/extensions/mini/pom.xml0000644000175000017500000000105211460132762017014 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-mini Google Guice - Extensions - Mini guice-3.0/extensions/mini/test/0000755000175000017500000000000011442650756016470 5ustar drazzibdrazzibguice-3.0/extensions/mini/test/com/0000755000175000017500000000000011442650756017246 5ustar drazzibdrazzibguice-3.0/extensions/mini/test/com/google/0000755000175000017500000000000011442650756020522 5ustar drazzibdrazzibguice-3.0/extensions/mini/test/com/google/inject/0000755000175000017500000000000011442650756021776 5ustar drazzibdrazzibguice-3.0/extensions/mini/test/com/google/inject/mini/0000755000175000017500000000000011445101174022716 5ustar drazzibdrazzibguice-3.0/extensions/mini/test/com/google/inject/mini/MiniGuiceTest.java0000644000175000017500000001244611445101174026301 0ustar drazzibdrazzib/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.mini; import com.google.inject.Provides; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; import junit.framework.TestCase; public final class MiniGuiceTest extends TestCase { public void testBasicInjection() { G g = MiniGuice.inject(G.class, new Object() { @Provides E provideE(F f) { return new E(f); } @Provides F provideF() { return new F(); } }); assertNotNull(g.a); assertNotNull(g.b); assertNotNull(g.c); assertNotNull(g.d); assertNotNull(g.e); assertNotNull(g.e.f); } static class A { @Inject A() {} } static class B { @Inject B() {} } @Singleton static class C { @Inject C() {} } @Singleton static class D { @Inject D() {} } static class E { F f; E(F f) { this.f = f; } } static class F {} static class G { @Inject A a; @Inject B b; C c; D d; @Inject E e; @Inject G(C c, D d) { this.c = c; this.d = d; } } public void testProviderInjection() { H h = MiniGuice.inject(H.class); assertNotNull(h.aProvider.get()); assertNotNull(h.aProvider.get()); assertNotSame(h.aProvider.get(), h.aProvider.get()); } static class H { @Inject Provider aProvider; @Inject H() {} } public void testSingletons() { J j = MiniGuice.inject(J.class, new Object() { @Provides @Singleton F provideK() { return new F(); } }); assertSame(j.fProvider.get(), j.fProvider.get()); assertSame(j.iProvider.get(), j.iProvider.get()); } @Singleton static class I { @Inject I() {} } static class J { @Inject Provider fProvider; @Inject Provider iProvider; @Inject J() {} } public void testBindingAnnotations() { final A one = new A(); final A two = new A(); K k = MiniGuice.inject(K.class, new Object() { @Provides @Named("one") A getOne() { return one; } @Provides @Named("two") A getTwo() { return two; } }); assertNotNull(k.a); assertSame(one, k.aOne); assertSame(two, k.aTwo); } public static class K { @Inject A a; @Inject @Named("one") A aOne; @Inject @Named("two") A aTwo; } public void testSingletonBindingAnnotationAndProvider() { final AtomicReference a1 = new AtomicReference(); final AtomicReference a2 = new AtomicReference(); L l = MiniGuice.inject(L.class, new Object() { @Provides @Singleton @Named("one") F provideF(Provider aProvider) { a1.set(aProvider.get()); a2.set(aProvider.get()); return new F(); } }); assertNotNull(a1.get()); assertNotNull(a2.get()); assertNotSame(a1.get(), a2.get()); assertSame(l, l.lProvider.get()); } @Singleton public static class L { @Inject @Named("one") F f; @Inject Provider lProvider; } public void testSingletonInGraph() { M m = MiniGuice.inject(M.class, new Object() { @Provides @Singleton F provideF() { return new F(); } }); assertSame(m.f1, m.f2); assertSame(m.f1, m.n1.f1); assertSame(m.f1, m.n1.f2); assertSame(m.f1, m.n2.f1); assertSame(m.f1, m.n2.f2); assertSame(m.f1, m.n1.fProvider.get()); assertSame(m.f1, m.n2.fProvider.get()); } public static class M { @Inject N n1; @Inject N n2; @Inject F f1; @Inject F f2; } public static class N { @Inject F f1; @Inject F f2; @Inject Provider fProvider; } public void testNoJitBindingsForAnnotations() { try { MiniGuice.inject(O.class); fail(); } catch (IllegalArgumentException expected) { } } public static class O { @Inject @Named("a") A a; } public void testSubclasses() { Q q = MiniGuice.inject(Q.class, new Object() { @Provides F provideF() { return new F(); } }); assertNotNull(q.f); } public static class P { @Inject F f; } public static class Q extends P { @Inject Q() {} } public void testSingletonsAreEager() { final AtomicBoolean sInjected = new AtomicBoolean(); R.injected = false; MiniGuice.inject(A.class, new Object() { @Provides F provideF(R r) { return new F(); } @Provides @Singleton S provideS() { sInjected.set(true); return new S(); } }); assertTrue(R.injected); assertTrue(sInjected.get()); } @Singleton static class R { static boolean injected = false; @Inject R() { injected = true; } } static class S {} } guice-3.0/extensions/mini/src/0000755000175000017500000000000011442650756016300 5ustar drazzibdrazzibguice-3.0/extensions/mini/src/com/0000755000175000017500000000000011442650756017056 5ustar drazzibdrazzibguice-3.0/extensions/mini/src/com/google/0000755000175000017500000000000011442650756020332 5ustar drazzibdrazzibguice-3.0/extensions/mini/src/com/google/inject/0000755000175000017500000000000011442650756021606 5ustar drazzibdrazzibguice-3.0/extensions/mini/src/com/google/inject/mini/0000755000175000017500000000000011445101174022526 5ustar drazzibdrazzibguice-3.0/extensions/mini/src/com/google/inject/mini/MiniGuice.java0000644000175000017500000003223611445101174025250 0ustar drazzibdrazzib/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.mini; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; import javax.inject.Provider; /** * Proof of concept. A tiny injector suitable for tiny applications. * * @author jessewilson@google.com (Jesse Wilson) * @since 3.0 */ public final class MiniGuice { private static final Object UNINITIALIZED = new Object(); private MiniGuice() {} private final Map> bindings = new HashMap>(); private final Queue requiredKeys = new ArrayDeque(); private final Set singletons = new HashSet(); /** * Creates an injector defined by {@code modules} and immediately uses it to * create an instance of {@code type}. The modules can be of any type, and * must contain {@code @Provides} methods. * *

The following injection features are supported: *

    *
  • Field injection. A class may have any number of field injections, and * fields may be of any visibility. Static fields will be injected each * time an instance is injected. *
  • Constructor injection. A class may have a single {@code * @Inject}-annotated constructor. Classes that have fields injected * may omit the {@link @Inject} annotation if they have a public * no-arguments constructor. *
  • Injection of {@code @Provides} method parameters. *
  • {@code @Provides} methods annotated {@code @Singleton}. *
  • Constructor-injected classes annotated {@code @Singleton}. *
  • Injection of {@link Provider}s. *
  • Binding annotations on injected parameters and fields. *
  • Guice annotations. *
  • JSR 330 annotations. *
  • Eager loading of singletons. *
* *

Note that method injection is not supported. */ public static T inject(Class type, Object... modules) { Key key = new Key(type, null); MiniGuice miniGuice = new MiniGuice(); for (Object module : modules) { miniGuice.install(module); } miniGuice.requireKey(key, "root injection"); miniGuice.addJitBindings(); miniGuice.addProviderBindings(); miniGuice.eagerlyLoadSingletons(); Provider provider = miniGuice.bindings.get(key); return type.cast(provider.get()); } private void addProviderBindings() { Map> providerBindings = new HashMap>(); for (final Map.Entry> binding : bindings.entrySet()) { Key key = binding.getKey(); final Provider value = binding.getValue(); Provider> providerProvider = new Provider>() { public Provider get() { return value; } }; providerBindings.put(new Key(new ProviderType(javax.inject.Provider.class, key.type), key.annotation), providerProvider); } bindings.putAll(providerBindings); } private void requireKey(Key key, Object requiredBy) { if (key.type instanceof ParameterizedType && (((ParameterizedType) key.type).getRawType() == Provider.class || ((ParameterizedType) key.type).getRawType() == javax.inject.Provider.class)) { Type type = ((ParameterizedType) key.type).getActualTypeArguments()[0]; key = new Key(type, key.annotation); } requiredKeys.add(new RequiredKey(key, requiredBy)); } private void eagerlyLoadSingletons() { for (Key key : singletons) { Provider provider = bindings.get(key); final Object onlyInstance = provider.get(); bindings.put(key, new Provider() { public Object get() { return onlyInstance; } }); } } public void install(Object module) { boolean hasProvidesMethods = false; for (Class c = module.getClass(); c != Object.class; c = c.getSuperclass()) { for (Method method : c.getDeclaredMethods()) { if (method.getAnnotation(com.google.inject.Provides.class) != null) { Key key = key(method, method.getGenericReturnType(), method.getAnnotations()); addProviderMethodBinding(key, module, method); hasProvidesMethods = true; } } } if (!hasProvidesMethods) { throw new IllegalArgumentException("No @Provides methods on " + module); } } private void addProviderMethodBinding(Key key, final Object instance, final Method method) { final Key[] parameterKeys = parametersToKeys( method, method.getGenericParameterTypes(), method.getParameterAnnotations()); method.setAccessible(true); final Provider unscoped = new Provider() { public Object get() { Object[] parameters = keysToValues(parameterKeys); try { return method.invoke(instance, parameters); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e.getCause()); } } }; boolean singleton = method.getAnnotation(javax.inject.Singleton.class) != null; putBinding(key, unscoped, singleton); } private void addJitBindings() { RequiredKey requiredKey; while ((requiredKey = requiredKeys.poll()) != null) { Key key = requiredKey.key; if (bindings.containsKey(key)) { continue; } if (!(key.type instanceof Class) || key.annotation != null) { throw new IllegalArgumentException("No binding for " + key); } addJitBinding(key, requiredKey.requiredBy); } } private void addJitBinding(Key key, Object requiredBy) { Class type = (Class) key.type; /* * Lookup the injectable fields and their corresponding keys. */ final List injectedFields = new ArrayList(); List fieldKeysList = new ArrayList(); for (Class c = type; c != Object.class; c = c.getSuperclass()) { for (Field field : c.getDeclaredFields()) { if (field.getAnnotation(javax.inject.Inject.class) == null) { continue; } field.setAccessible(true); injectedFields.add(field); Key fieldKey = key(field, field.getGenericType(), field.getAnnotations()); fieldKeysList.add(fieldKey); requireKey(fieldKey, field); } } final Key[] fieldKeys = fieldKeysList.toArray(new Key[fieldKeysList.size()]); /* * Lookup @Inject-annotated constructors. If there's no @Inject-annotated * constructor, use a default constructor if the class has other injections. */ Constructor injectedConstructor = null; for (Constructor constructor : type.getDeclaredConstructors()) { if (constructor.getAnnotation(javax.inject.Inject.class) == null) { continue; } if (injectedConstructor != null) { throw new IllegalArgumentException("Too many injectable constructors on " + type); } constructor.setAccessible(true); injectedConstructor = constructor; } if (injectedConstructor == null) { if (fieldKeys.length == 0) { throw new IllegalArgumentException("No injectable constructor on " + type + " required by " + requiredBy); } try { injectedConstructor = type.getConstructor(); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("No injectable constructor on " + type + " required by " + requiredBy); } } /* * Create a provider that invokes the constructor and sets its fields. */ final Constructor constructor = injectedConstructor; final Key[] parameterKeys = parametersToKeys( constructor, constructor.getGenericParameterTypes(), constructor.getParameterAnnotations()); final Provider unscoped = new Provider() { public Object get() { Object[] constructorParameters = keysToValues(parameterKeys); try { Object result = constructor.newInstance(constructorParameters); Object[] fieldValues = keysToValues(fieldKeys); for (int i = 0; i < fieldValues.length; i++) { injectedFields.get(i).set(result, fieldValues[i]); } return result; } catch (IllegalAccessException e) { throw new RuntimeException(e.getCause()); } catch (InvocationTargetException e) { throw new RuntimeException(e.getCause()); } catch (InstantiationException e) { throw new RuntimeException(e); } } }; boolean singleton = type.getAnnotation(javax.inject.Singleton.class) != null; putBinding(new Key(type, null), unscoped, singleton); } private void putBinding(Key key, Provider provider, boolean singleton) { if (singleton) { singletons.add(key); final Provider unscoped = provider; provider = new Provider() { private Object onlyInstance = UNINITIALIZED; public Object get() { if (onlyInstance == UNINITIALIZED) { onlyInstance = unscoped.get(); } return onlyInstance; } }; } if (bindings.put(key, provider) != null) { throw new IllegalArgumentException("Duplicate binding " + key); } } private Object[] keysToValues(Key[] parameterKeys) { Object[] parameters = new Object[parameterKeys.length]; for (int i = 0; i < parameterKeys.length; i++) { parameters[i] = bindings.get(parameterKeys[i]).get(); } return parameters; } private Key[] parametersToKeys(Member member, Type[] types, Annotation[][] annotations) { final Key[] parameterKeys = new Key[types.length]; for (int i = 0; i < parameterKeys.length; i++) { String name = member + " parameter " + i; parameterKeys[i] = key(name, types[i], annotations[i]); requireKey(parameterKeys[i], name); } return parameterKeys; } public Key key(Object subject, Type type, Annotation[] annotations) { Annotation bindingAnnotation = null; for (Annotation a : annotations) { if (a.annotationType().getAnnotation(javax.inject.Qualifier.class) == null) { continue; } if (bindingAnnotation != null) { throw new IllegalArgumentException("Too many binding annotations on " + subject); } bindingAnnotation = a; } return new Key(type, bindingAnnotation); } private static boolean equal(Object a, Object b) { return a == null ? b == null : a.equals(b); } private static final class Key { final Type type; final Annotation annotation; Key(Type type, Annotation annotation) { this.type = type; this.annotation = annotation; } @Override public boolean equals(Object o) { return o instanceof Key && ((Key) o).type.equals(type) && equal(annotation, ((Key) o).annotation); } @Override public int hashCode() { int result = type.hashCode(); if (annotation != null) { result += (37 * annotation.hashCode()); } return result; } @Override public String toString() { return "key[type=" + type + ",annotation=" + annotation + "]"; } } private class RequiredKey { private final Key key; private final Object requiredBy; private RequiredKey(Key key, Object requiredBy) { this.key = key; this.requiredBy = requiredBy; } } private static final class ProviderType implements ParameterizedType { private final Class rawType; private final Type typeArgument; public ProviderType(Class rawType, Type typeArgument) { this.rawType = rawType; this.typeArgument = typeArgument; } public Type getRawType() { return rawType; } public Type[] getActualTypeArguments() { return new Type[] { typeArgument }; } public Type getOwnerType() { return null; } @Override public boolean equals(Object o) { if (o instanceof ParameterizedType) { ParameterizedType that = (ParameterizedType) o; return Arrays.equals(getActualTypeArguments(), that.getActualTypeArguments()) && that.getRawType() == rawType; } return false; } @Override public int hashCode() { return Arrays.hashCode(getActualTypeArguments()) ^ rawType.hashCode(); } } } guice-3.0/extensions/pom.xml0000644000175000017500000000724011510705016016057 0ustar drazzibdrazzib 4.0.0 com.google.inject guice-parent 3.0-SNAPSHOT pom com.google.inject.extensions extensions-parent Google Guice - Extensions assistedinject grapher jmx jndi multibindings persist servlet spring struts2 throwingproviders com.google.inject guice ${project.version} com.google.inject guice ${project.version} tests test maven-remote-resources-plugin org.codehaus.mojo animal-sniffer-maven-plugin org.apache.felix maven-bundle-plugin com.google.inject guice.with.jarjar guice.with.jarjar !false com.google.inject guice ${project.version} no_deps true org.sonatype.plugins jarjar-maven-plugin *:* guice-3.0/extensions/service/0000755000175000017500000000000011464433216016207 5ustar drazzibdrazzibguice-3.0/extensions/service/pom.xml0000644000175000017500000000106011464433216017521 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-service Google Guice - Extensions - Service guice-3.0/extensions/service/service.iml0000644000175000017500000000105011445101174020340 0ustar drazzibdrazzib guice-3.0/extensions/service/test/0000755000175000017500000000000011445101174017160 5ustar drazzibdrazzibguice-3.0/extensions/service/test/com/0000755000175000017500000000000011445101174017736 5ustar drazzibdrazzibguice-3.0/extensions/service/test/com/google/0000755000175000017500000000000011445101174021212 5ustar drazzibdrazzibguice-3.0/extensions/service/test/com/google/inject/0000755000175000017500000000000011445101174022466 5ustar drazzibdrazzibguice-3.0/extensions/service/test/com/google/inject/service/0000755000175000017500000000000011445101174024126 5ustar drazzibdrazzibguice-3.0/extensions/service/test/com/google/inject/service/SingleServiceIntegrationTest.java0000644000175000017500000000415111445101174032600 0ustar drazzibdrazzibpackage com.google.inject.service; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import junit.framework.TestCase; /** * Tests using Async Service. */ public class SingleServiceIntegrationTest extends TestCase { public final void testAsyncServiceLifecycle() throws InterruptedException { ExecutorService executor = Executors.newSingleThreadExecutor(); final CountDownLatch startLatch = new CountDownLatch(1); final CountDownLatch stopLatch = new CountDownLatch(1); AsyncService service = new AsyncService(executor) { @Override protected void onStart() { assertEquals(1, startLatch.getCount()); assertEquals(1, stopLatch.getCount()); startLatch.countDown(); } @Override protected void onStop() { assertEquals(0, startLatch.getCount()); assertEquals(1, stopLatch.getCount()); stopLatch.countDown(); } }; service.start(); // This should not pass! assertTrue(startLatch.await(2, TimeUnit.SECONDS)); service.stop(); assertTrue(stopLatch.await(2, TimeUnit.SECONDS)); executor.shutdown(); assertEquals(0, startLatch.getCount()); assertEquals(0, stopLatch.getCount()); } public final void testAsyncServiceBlockingLifecycle() throws InterruptedException, ExecutionException, TimeoutException { ExecutorService executor = Executors.newSingleThreadExecutor(); final AtomicInteger integer = new AtomicInteger(2); AsyncService service = new AsyncService(executor) { @Override protected void onStart() { assertEquals(2, integer.getAndDecrement()); } @Override protected void onStop() { assertEquals(1, integer.getAndDecrement()); } }; service.start().get(2, TimeUnit.SECONDS); service.stop().get(2, TimeUnit.SECONDS); executor.shutdown(); assertEquals(0, integer.get()); } } guice-3.0/extensions/service/src/0000755000175000017500000000000011445101174016770 5ustar drazzibdrazzibguice-3.0/extensions/service/src/com/0000755000175000017500000000000011445101174017546 5ustar drazzibdrazzibguice-3.0/extensions/service/src/com/google/0000755000175000017500000000000011445101174021022 5ustar drazzibdrazzibguice-3.0/extensions/service/src/com/google/inject/0000755000175000017500000000000011445101174022276 5ustar drazzibdrazzibguice-3.0/extensions/service/src/com/google/inject/service/0000755000175000017500000000000011445101174023736 5ustar drazzibdrazzibguice-3.0/extensions/service/src/com/google/inject/service/Service.java0000644000175000017500000000500611445101174026202 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.service; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; /** * An object with an operational state, asynchronous {@link #start()} and * {@link #stop()} lifecycle methods to transition in and out of this state. * Example services include http servers, RPC systems and timer tasks. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public interface Service { /** * If the service has already been started, this method returns * immediately without taking action. A stopped service may not be restarted. * * @return a future for the startup result, regardless of whether this call * initiated startup. Calling {@link Future#get} will block until the * service has finished starting, and returns the resultant state. If * the service fails to start, {@link Future#get} will throw an {@link * ExecutionException}. If it has already finished starting, * {@link Future#get} returns immediately. */ Future start(); /** * If the service is {@link State#STARTED} initiates service shutdown and * returns immediately. If the service has already been stopped, this * method returns immediately without taking action. * * @return a future for the shutdown result, regardless of whether this call * initiated shutdown. Calling {@link Future#get} will block until the * service has finished shutting down, and either returns {@link * State#STOPPED} or throws an {@link ExecutionException}. If it has * already finished stopping, {@link Future#get} returns immediately. */ Future stop(); /** * Returns the current state of this service. One of {@link State} possible * values, or null if this is a brand new object, i.e., has not been put into * any state yet. */ State state(); /** * The lifecycle states of a service. */ enum State { STARTED, STOPPED, FAILED } } guice-3.0/extensions/service/src/com/google/inject/service/CompositeService.java0000644000175000017500000000762111445101174030072 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.service; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Preconditions; import com.google.inject.internal.util.Sets; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; /** * A service that composes other services together in a fixed order. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class CompositeService { private final Injector injector; private final Set> services = Sets.newLinkedHashSet(); /** * Represents the state of this composite service. Will equal FAILED * even if only one component service fails to start or stop. In other * words, all component services must start successfully for this * service to be considered started and similarly for stopped. */ private volatile Service.State compositeState; private boolean composed; @Inject CompositeService(Injector injector) { this.injector = injector; } public CompositeService add(Class service) { return add(Key.get(service)); } public CompositeService add(Key service) { Preconditions.checkState(!composed, "Cannot reuse a CompositeService after it has been compose()d. Please create a new one."); // Verify that the binding exists. Throws an exception if not. injector.getBinding(service); services.add(service); return this; } public Service compose() { Preconditions.checkState(!composed, "Cannot reuse a CompositeService after it has been compose()d. Please create a new one."); composed = true; // Defensive copy. final List> services = ImmutableList.copyOf(this.services); return new Service() { public Future start() { final List> tasks = Lists.newArrayList(); for (Key service : services) { tasks.add(injector.getInstance(service).start()); } return futureGet(tasks, State.STARTED); } public Future stop() { final List> tasks = Lists.newArrayList(); for (Key service : services) { tasks.add(injector.getInstance(service).stop()); } return futureGet(tasks, State.STOPPED); } public State state() { return compositeState; } }; } private FutureTask futureGet(final List> tasks, final Service.State state) { return new FutureTask(new Callable() { public Service.State call() { boolean ok = true; for (Future task : tasks) { try { ok = state == task.get(); } catch (InterruptedException e) { return compositeState = Service.State.FAILED; } catch (ExecutionException e) { return compositeState = Service.State.FAILED; } } return compositeState = ok ? state : Service.State.FAILED; } }); } } guice-3.0/extensions/service/src/com/google/inject/service/AsyncService.java0000644000175000017500000000575611445101174027214 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.service; import com.google.inject.internal.util.Preconditions; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; /** * An asynchronous implementation of {@link com.google.inject.service.Service} * that provides convenience callbacks to create your own services. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public abstract class AsyncService implements Service { private final ExecutorService executor; /** * A runnable that does nothing. */ private static final Runnable NOOP = new Runnable() { public void run() { } }; private volatile State state; public AsyncService(ExecutorService executor) { this.executor = executor; } public synchronized final Future start() { Preconditions.checkState(state != State.STOPPED, "Cannot restart a service that has been stopped"); // Starts are idempotent. if (state == State.STARTED) { return new FutureTask(NOOP, State.STARTED); } return executor.submit(new Callable() { public State call() { onStart(); return state = State.STARTED; } }); } /** * Called back when this service must do its start work. Typically occurs * in a background thread. The result of this method is returned to the * original caller of {@link Service#start()} and can thus be used to * return a status message after start completes (or fails as the case * may be). */ protected abstract void onStart(); public synchronized final Future stop() { Preconditions.checkState(state != null, "Must start this service before you stop it!"); // Likewise, stops are idempotent. if (state == State.STOPPED) { return new FutureTask(NOOP, State.STOPPED); } return executor.submit(new Callable() { public State call() { onStop(); return state = State.STOPPED; } }); } /** * Called back when this service must shutdown. Typically occurs * in a background thread. The result of this method is returned to the * original caller of {@link Service#stop()} and can thus be used to * return a status message after stop completes (or fails as the case * may be). */ protected abstract void onStop(); public final State state() { return state; } } guice-3.0/extensions/struts2/0000755000175000017500000000000011542727752016205 5ustar drazzibdrazzibguice-3.0/extensions/struts2/build/0000755000175000017500000000000011542727752017304 5ustar drazzibdrazzibguice-3.0/extensions/struts2/build/META-INF/0000755000175000017500000000000011542727752020444 5ustar drazzibdrazzibguice-3.0/extensions/struts2/build/META-INF/MANIFEST.MF0000644000175000017500000000150111542727750022071 0ustar drazzibdrazzibManifest-Version: 1.0 Export-Package: com.google.inject.struts2;version="1.3" Bundle-Name: guice-struts2-plugin Created-By: 1.6.0_23 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-Copyright: Copyright (C) 2006 Google Inc. Bundle-Vendor: Google, Inc. Fragment-Host: com.google.inject Bundle-Version: 3.0 Bundle-ManifestVersion: 2 Bundle-Description: Guice is a lightweight dependency injection framew ork for Java 5 and above Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-DocURL: http://code.google.com/p/google-guice/ Bundle-SymbolicName: com.google.inject.struts2 Import-Package: com.opensymphony.xwork2,com.opensymphony.xwork2.config ,com.opensymphony.xwork2.config.entities,com.opensymphony.xwork2.inje ct,com.opensymphony.xwork2.interceptor guice-3.0/extensions/struts2/build/dist/0000755000175000017500000000000011542727752020247 5ustar drazzibdrazzibguice-3.0/extensions/struts2/build/classes/0000755000175000017500000000000011542727752020741 5ustar drazzibdrazzibguice-3.0/extensions/struts2/build/classes/struts-plugin.xml0000644000175000017500000000072111542727752024323 0ustar drazzibdrazzib guice-3.0/extensions/struts2/build/classes/com/0000755000175000017500000000000011542727752021517 5ustar drazzibdrazzibguice-3.0/extensions/struts2/build/classes/com/google/0000755000175000017500000000000011542727752022773 5ustar drazzibdrazzibguice-3.0/extensions/struts2/build/classes/com/google/inject/0000755000175000017500000000000011542727752024247 5ustar drazzibdrazzibguice-3.0/extensions/struts2/build/classes/com/google/inject/struts2/0000755000175000017500000000000011542727752025675 5ustar drazzibdrazzibguice-3.0/extensions/struts2/pom.xml0000644000175000017500000000220111477764304017516 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-struts2 Google Guice - Extensions - Struts2 com.google.inject.extensions guice-servlet ${project.version} javax.servlet servlet-api 2.5 provided org.apache.struts struts2-core 2.2.1 provided guice-3.0/extensions/struts2/build.xml0000644000175000017500000000133511477764304020031 0ustar drazzibdrazzib guice-3.0/extensions/struts2/plugin/0000755000175000017500000000000011477764304017504 5ustar drazzibdrazzibguice-3.0/extensions/struts2/lib/0000755000175000017500000000000011477764302016752 5ustar drazzibdrazzibguice-3.0/extensions/struts2/build.properties0000644000175000017500000000017311477764304021424 0ustar drazzibdrazziblib.dir=../../lib ext.lib.dir=lib src.dir=src test.dir=test build.dir=build module=com.google.inject.struts2 fragment=true guice-3.0/extensions/struts2/test/0000755000175000017500000000000011477764230017163 5ustar drazzibdrazzibguice-3.0/extensions/struts2/test/com/0000755000175000017500000000000011477764230017741 5ustar drazzibdrazzibguice-3.0/extensions/struts2/test/com/google/0000755000175000017500000000000011477764230021215 5ustar drazzibdrazzibguice-3.0/extensions/struts2/test/com/google/inject/0000755000175000017500000000000011477764230022471 5ustar drazzibdrazzibguice-3.0/extensions/struts2/test/com/google/inject/struts2/0000755000175000017500000000000011477764230024117 5ustar drazzibdrazzibguice-3.0/extensions/struts2/test/com/google/inject/struts2/Struts2FactoryTest.java0000644000175000017500000000456611477772212030552 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.struts2; import java.util.Date; import junit.framework.TestCase; import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.Provides; import com.google.inject.Singleton; import com.google.inject.servlet.GuiceServletContextListener; import com.google.inject.servlet.ServletModule; /** * Test for Struts2Factory * * @author benmccann.com */ public class Struts2FactoryTest extends TestCase { private static final Date TODAY = new Date(); public static class TestListener extends GuiceServletContextListener { private final Module module; public TestListener(Module module) { this.module = module; } @Override protected Injector getInjector() { return Guice.createInjector( new Struts2GuicePluginModule(), new ServletModule() { @Override protected void configureServlets() { // Struts 2 setup bind(StrutsPrepareAndExecuteFilter.class).in(Singleton.class); filter("/*").through(StrutsPrepareAndExecuteFilter.class); } }, module ); } } public void testStruts2Factory() { Struts2Factory s2Factory = new Struts2Factory(); TestListener testListener = new TestListener(new AbstractModule() { @Override protected void configure() { } @Provides @SuppressWarnings("unused") Date provideDate() { return TODAY; } }); assertEquals(TODAY, testListener.getInjector().getInstance(Date.class)); assertEquals(TODAY, s2Factory.buildBean(Date.class, null)); } } guice-3.0/extensions/struts2/src/0000755000175000017500000000000011477764302016773 5ustar drazzibdrazzibguice-3.0/extensions/struts2/src/struts-plugin.xml0000644000175000017500000000072111477764302022355 0ustar drazzibdrazzib guice-3.0/extensions/struts2/src/com/0000755000175000017500000000000011477764302017551 5ustar drazzibdrazzibguice-3.0/extensions/struts2/src/com/google/0000755000175000017500000000000011477764302021025 5ustar drazzibdrazzibguice-3.0/extensions/struts2/src/com/google/inject/0000755000175000017500000000000011477764302022301 5ustar drazzibdrazzibguice-3.0/extensions/struts2/src/com/google/inject/struts2/0000755000175000017500000000000011521017776023723 5ustar drazzibdrazzibguice-3.0/extensions/struts2/src/com/google/inject/struts2/Struts2GuicePluginModule.java0000644000175000017500000000177511521017776031470 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.struts2; import com.google.inject.AbstractModule; /** * Initializes the Struts 2 Guice Plugin. * Must be added to the injector returned by * {@link GuiceServletContextListener.getInjector()}. * * @author benmccann.com */ public class Struts2GuicePluginModule extends AbstractModule { @Override protected void configure() { requestStaticInjection(Struts2Factory.class); } } guice-3.0/extensions/struts2/src/com/google/inject/struts2/GuiceObjectFactory.java0000644000175000017500000001664511477764302030321 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.struts2; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.internal.Annotations; import com.google.inject.servlet.ServletModule; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ObjectFactory; import com.opensymphony.xwork2.config.ConfigurationException; import com.opensymphony.xwork2.config.entities.InterceptorConfig; import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.interceptor.Interceptor; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; /** * @deprecated Use {@link com.google.inject.servlet.Struts2Factory} instead. */ @Deprecated public class GuiceObjectFactory extends ObjectFactory { static final Logger logger = Logger.getLogger(GuiceObjectFactory.class.getName()); Module module; volatile Injector injector; boolean developmentMode = false; List interceptors = new ArrayList(); @Override public boolean isNoArgConstructorRequired() { return false; } @Inject(value = "guice.module", required = false) void setModule(String moduleClassName) { try { // Instantiate user's module. @SuppressWarnings({"unchecked"}) Class moduleClass = (Class) Class.forName(moduleClassName); this.module = moduleClass.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } @Inject(value = "struts.devMode", required = false) void setDevelopmentMode(String developmentMode) { this.developmentMode = developmentMode.trim().equals("true"); } Set> boundClasses = new HashSet>(); public Class getClassInstance(String name) throws ClassNotFoundException { Class clazz = super.getClassInstance(name); synchronized (this) { if (injector == null) { // We can only bind each class once. if (!boundClasses.contains(clazz)) { try { // Calling these methods now helps us detect ClassNotFoundErrors // early. clazz.getDeclaredFields(); clazz.getDeclaredMethods(); boundClasses.add(clazz); } catch (Throwable t) { // Struts should still work even though some classes aren't in the // classpath. It appears we always get the exception here when // this is the case. return clazz; } } } } return clazz; } @SuppressWarnings("unchecked") public Object buildBean(Class clazz, Map extraContext) { if (injector == null) { synchronized (this) { if (injector == null) { createInjector(); } } } return injector.getInstance(clazz); } private void createInjector() { try { logger.info("Creating injector..."); this.injector = Guice.createInjector(new AbstractModule() { protected void configure() { // Install default servlet bindings. install(new ServletModule()); // Install user's module. if (module != null) { logger.info("Installing " + module + "..."); install(module); } else { logger.info("No module found. Set 'guice.module' to a Module " + "class name if you'd like to use one."); } // Tell the injector about all the action classes, etc., so it // can validate them at startup. for (Class boundClass : boundClasses) { // TODO: Set source from Struts XML. bind(boundClass); } // Validate the interceptor class. for (ProvidedInterceptor interceptor : interceptors) { interceptor.validate(binder()); } } }); // Inject interceptors. for (ProvidedInterceptor interceptor : interceptors) { interceptor.inject(); } } catch (Throwable t) { t.printStackTrace(); System.exit(1); } logger.info("Injector created successfully."); } @SuppressWarnings("unchecked") public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams) throws ConfigurationException { // Ensure the interceptor class is present. Class interceptorClass; try { interceptorClass = getClassInstance(interceptorConfig.getClassName()); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } ProvidedInterceptor providedInterceptor = new ProvidedInterceptor( interceptorConfig, interceptorRefParams, interceptorClass); interceptors.add(providedInterceptor); return providedInterceptor; } Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams) throws ConfigurationException { return super.buildInterceptor(interceptorConfig, interceptorRefParams); } class ProvidedInterceptor implements Interceptor { final InterceptorConfig config; final Map params; final Class interceptorClass; Interceptor delegate; ProvidedInterceptor(InterceptorConfig config, Map params, Class interceptorClass) { this.config = config; this.params = params; this.interceptorClass = interceptorClass; } void validate(Binder binder) { // TODO: Set source from Struts XML. if (hasScope(interceptorClass)) { binder.addError("Scoping interceptors is not currently supported." + " Please remove the scope annotation from " + interceptorClass.getName() + "."); } // Make sure it implements Interceptor. if (!Interceptor.class.isAssignableFrom(interceptorClass)) { binder.addError(interceptorClass.getName() + " must implement " + Interceptor.class.getName() + "."); } } void inject() { delegate = superBuildInterceptor(config, params); } public void destroy() { if (null != delegate) { delegate.destroy(); } } public void init() { throw new AssertionError(); } public String intercept(ActionInvocation invocation) throws Exception { return delegate.intercept(invocation); } } /** * Returns true if the given class has a scope annotation. */ private static boolean hasScope(Class interceptorClass) { for (Annotation annotation : interceptorClass.getAnnotations()) { if (Annotations.isScopeAnnotation(annotation.annotationType())) { return true; } } return false; } } guice-3.0/extensions/struts2/src/com/google/inject/struts2/Struts2Factory.java0000644000175000017500000001657511521017776027522 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.struts2; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Injector; import com.google.inject.internal.Annotations; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ObjectFactory; import com.opensymphony.xwork2.config.ConfigurationException; import com.opensymphony.xwork2.config.entities.InterceptorConfig; import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.interceptor.Interceptor; /** * Cleanup up version from Bob's GuiceObjectFactory. Now works properly with * GS2 and fixes several bugs. * * @author dhanji@gmail.com * @author benmccann.com */ public class Struts2Factory extends ObjectFactory { private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(Struts2Factory.class.getName()); private static final String ERROR_NO_INJECTOR = "Cannot find a Guice injector. Are you sure you registered a GuiceServletContextListener " + "that uses the Struts2GuicePluginModule in your application's web.xml?"; private static @com.google.inject.Inject Injector injector; private final List interceptors = new ArrayList(); private volatile Injector strutsInjector; @Override public boolean isNoArgConstructorRequired() { return false; } @Inject(value = "guice.module", required = false) void setModule(String moduleClassName) { throw new RuntimeException("The struts2 plugin no longer supports" + " specifying a module via the 'guice.module' property in XML." + " Please install your module via a GuiceServletContextListener instead."); } Set> boundClasses = new HashSet>(); public Class getClassInstance(String name) throws ClassNotFoundException { Class clazz = super.getClassInstance(name); synchronized (this) { if (strutsInjector == null) { // We can only bind each class once. if (!boundClasses.contains(clazz)) { try { // Calling these methods now helps us detect ClassNotFoundErrors // early. clazz.getDeclaredFields(); clazz.getDeclaredMethods(); boundClasses.add(clazz); } catch (Throwable t) { // Struts should still work even though some classes aren't in the // classpath. It appears we always get the exception here when // this is the case. return clazz; } } } } return clazz; } @Override @SuppressWarnings("unchecked") public Object buildBean(Class clazz, Map extraContext) { if (strutsInjector == null) { synchronized (this) { if (strutsInjector == null) { createInjector(); } } } return strutsInjector.getInstance(clazz); } private void createInjector() { logger.info("Loading struts2 Guice support..."); // Something is wrong, since this should be there if GuiceServletContextListener // was present. if (injector == null) { logger.severe(ERROR_NO_INJECTOR); throw new RuntimeException(ERROR_NO_INJECTOR); } this.strutsInjector = injector.createChildInjector(new AbstractModule() { protected void configure() { // Tell the injector about all the action classes, etc., so it // can validate them at startup. for (Class boundClass : boundClasses) { // TODO: Set source from Struts XML. bind(boundClass); } // Validate the interceptor class. for (ProvidedInterceptor interceptor : interceptors) { interceptor.validate(binder()); } } }); // Inject interceptors. for (ProvidedInterceptor interceptor : interceptors) { interceptor.inject(); } logger.info("Injector created successfully."); } @SuppressWarnings("unchecked") public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams) throws ConfigurationException { // Ensure the interceptor class is present. Class interceptorClass; try { interceptorClass = (Class) getClassInstance(interceptorConfig.getClassName()); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } ProvidedInterceptor providedInterceptor = new ProvidedInterceptor( interceptorConfig, interceptorRefParams, interceptorClass); interceptors.add(providedInterceptor); return providedInterceptor; } private Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams) throws ConfigurationException { return super.buildInterceptor(interceptorConfig, interceptorRefParams); } private class ProvidedInterceptor implements Interceptor { private static final long serialVersionUID = 1L; private final InterceptorConfig config; private final Map params; private final Class interceptorClass; private Interceptor delegate; ProvidedInterceptor(InterceptorConfig config, Map params, Class interceptorClass) { this.config = config; this.params = params; this.interceptorClass = interceptorClass; } void validate(Binder binder) { // TODO: Set source from Struts XML. if (hasScope(interceptorClass)) { binder.addError("Scoping interceptors is not currently supported." + " Please remove the scope annotation from " + interceptorClass.getName() + "."); } // Make sure it implements Interceptor. if (!Interceptor.class.isAssignableFrom(interceptorClass)) { binder.addError(interceptorClass.getName() + " must implement " + Interceptor.class.getName() + "."); } } void inject() { delegate = superBuildInterceptor(config, params); } public void destroy() { if (null != delegate) { delegate.destroy(); } } public void init() { throw new AssertionError(); } public String intercept(ActionInvocation invocation) throws Exception { return delegate.intercept(invocation); } } /** * Returns true if the given class has a scope annotation. */ private static boolean hasScope(Class interceptorClass) { for (Annotation annotation : interceptorClass.getAnnotations()) { if (Annotations.isScopeAnnotation(annotation.annotationType())) { return true; } } return false; } } guice-3.0/extensions/struts2/example/0000755000175000017500000000000011477764304017641 5ustar drazzibdrazzibguice-3.0/extensions/struts2/example/struts2-example.iml0000644000175000017500000000756211477764304023435 0ustar drazzibdrazzib guice-3.0/extensions/struts2/example/build.xml0000644000175000017500000000045511477764304021466 0ustar drazzibdrazzib guice-3.0/extensions/struts2/example/root/0000755000175000017500000000000011477764304020624 5ustar drazzibdrazzibguice-3.0/extensions/struts2/example/root/WEB-INF/0000755000175000017500000000000011477764304021653 5ustar drazzibdrazzibguice-3.0/extensions/struts2/example/root/WEB-INF/web.xml0000644000175000017500000000102611477767246023161 0ustar drazzibdrazzib com.google.inject.struts2.example.ExampleListener guice com.google.inject.servlet.GuiceFilter guice /* guice-3.0/extensions/struts2/example/root/Counter.jsp0000644000175000017500000000047211477764304022764 0ustar drazzibdrazzib<%@ taglib prefix="s" uri="/struts-tags" %>

Counter Example

Hits in this session:

Status:

Message:

guice-3.0/extensions/struts2/example/build.properties0000644000175000017500000000005311477764304023054 0ustar drazzibdrazziblib.dir=../lib src.dir=src build.dir=build guice-3.0/extensions/struts2/example/src/0000755000175000017500000000000011477764304020430 5ustar drazzibdrazzibguice-3.0/extensions/struts2/example/src/struts.xml0000644000175000017500000000106511477767236022527 0ustar drazzibdrazzib /Counter.jsp guice-3.0/extensions/struts2/example/src/com/0000755000175000017500000000000011477764304021206 5ustar drazzibdrazzibguice-3.0/extensions/struts2/example/src/com/google/0000755000175000017500000000000011477764304022462 5ustar drazzibdrazzibguice-3.0/extensions/struts2/example/src/com/google/inject/0000755000175000017500000000000011477764304023736 5ustar drazzibdrazzibguice-3.0/extensions/struts2/example/src/com/google/inject/struts2/0000755000175000017500000000000011477764304025364 5ustar drazzibdrazzibguice-3.0/extensions/struts2/example/src/com/google/inject/struts2/example/0000755000175000017500000000000011477764304027017 5ustar drazzibdrazzibguice-3.0/extensions/struts2/example/src/com/google/inject/struts2/example/ServiceImpl.java0000644000175000017500000000024111477764304032101 0ustar drazzibdrazzibpackage com.google.inject.struts2.example; public class ServiceImpl implements Service { public String getStatus() { return "We're looking good."; } } guice-3.0/extensions/struts2/example/src/com/google/inject/struts2/example/ExampleListener.java0000644000175000017500000000313411477764304032764 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.struts2.example; import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Singleton; import com.google.inject.servlet.GuiceServletContextListener; import com.google.inject.servlet.ServletModule; import com.google.inject.struts2.Struts2GuicePluginModule; /** * Example application module. * * @author crazybob@google.com (Bob Lee) */ public class ExampleListener extends GuiceServletContextListener { public Injector getInjector() { return Guice.createInjector( new Struts2GuicePluginModule(), new ServletModule() { @Override protected void configureServlets() { // Struts 2 setup bind(StrutsPrepareAndExecuteFilter.class).in(Singleton.class); filter("/*").through(StrutsPrepareAndExecuteFilter.class); // Our app-specific code bind(Service.class).to(ServiceImpl.class); } }); } } guice-3.0/extensions/struts2/example/src/com/google/inject/struts2/example/Service.java0000644000175000017500000000014011477764304031255 0ustar drazzibdrazzibpackage com.google.inject.struts2.example; public interface Service { String getStatus(); } guice-3.0/extensions/struts2/example/src/com/google/inject/struts2/example/Count.java0000644000175000017500000000235211477764304030754 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.struts2.example; import com.google.inject.Inject; import static com.opensymphony.xwork2.Action.SUCCESS; public class Count { final Counter counter; final Service service; String message; @Inject public Count(Counter counter, Service service) { this.counter = counter; this.service = service; } public String execute() { return SUCCESS; } public int getCount() { return counter.increment(); } public String getStatus() { return service.getStatus(); } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } guice-3.0/extensions/struts2/example/src/com/google/inject/struts2/example/Counter.java0000644000175000017500000000161111477764304031300 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.struts2.example; import com.google.inject.servlet.SessionScoped; /** * Session-scoped counter. */ @SessionScoped public class Counter { int count = 0; /** Increments the count and returns the new value. */ public synchronized int increment() { return count++; } } guice-3.0/extensions/struts2/example/src/com/google/inject/struts2/example/Main.java0000644000175000017500000000242411477764304030550 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.struts2.example; import org.mortbay.jetty.Connector; import org.mortbay.jetty.Server; import org.mortbay.jetty.nio.SelectChannelConnector; import org.mortbay.jetty.webapp.WebAppContext; /** * Starts the example web server on port 8080. Run from "./struts2/example". */ public class Main { public static void main(String[] args) throws Exception { Server server = new Server(); Connector connector = new SelectChannelConnector(); connector.setPort(8080); server.setConnectors(new Connector[] { connector }); WebAppContext webapp = new WebAppContext("./root", "/example"); server.addHandler(webapp); server.start(); server.join(); } } guice-3.0/extensions/struts2/struts2-plugin.iml0000644000175000017500000000741211477764304021637 0ustar drazzibdrazzib guice-3.0/extensions/jmx/0000755000175000017500000000000011542727752015355 5ustar drazzibdrazzibguice-3.0/extensions/jmx/build/0000755000175000017500000000000011542727754016456 5ustar drazzibdrazzibguice-3.0/extensions/jmx/build/META-INF/0000755000175000017500000000000011542727754017616 5ustar drazzibdrazzibguice-3.0/extensions/jmx/build/META-INF/MANIFEST.MF0000644000175000017500000000122311542727752021244 0ustar drazzibdrazzibManifest-Version: 1.0 Export-Package: com.google.inject.tools.jmx;version="1.3" Bundle-Name: guice-jmx Created-By: 1.6.0_23 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-Copyright: Copyright (C) 2006 Google Inc. Bundle-Vendor: Google, Inc. Bundle-Version: 3.0 Bundle-ManifestVersion: 2 Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-Description: Guice is a lightweight dependency injection framew ork for Java 5 and above Bundle-DocURL: http://code.google.com/p/google-guice/ Import-Package: com.google.inject,javax.management Bundle-SymbolicName: com.google.inject.tools.jmx guice-3.0/extensions/jmx/build/dist/0000755000175000017500000000000011542727752017417 5ustar drazzibdrazzibguice-3.0/extensions/jmx/build/classes/0000755000175000017500000000000011542727752020111 5ustar drazzibdrazzibguice-3.0/extensions/jmx/build/classes/com/0000755000175000017500000000000011542727752020667 5ustar drazzibdrazzibguice-3.0/extensions/jmx/build/classes/com/google/0000755000175000017500000000000011542727752022143 5ustar drazzibdrazzibguice-3.0/extensions/jmx/build/classes/com/google/inject/0000755000175000017500000000000011542727752023417 5ustar drazzibdrazzibguice-3.0/extensions/jmx/build/classes/com/google/inject/tools/0000755000175000017500000000000011542727752024557 5ustar drazzibdrazzibguice-3.0/extensions/jmx/build/classes/com/google/inject/tools/jmx/0000755000175000017500000000000011542727752025355 5ustar drazzibdrazzibguice-3.0/extensions/jmx/pom.xml0000644000175000017500000000105011460132762016654 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-jmx Google Guice - Extensions - JMX guice-3.0/extensions/jmx/build.xml0000644000175000017500000000123611461503344017165 0ustar drazzibdrazzib guice-3.0/extensions/jmx/jmx.iml0000644000175000017500000000107511214265014016641 0ustar drazzibdrazzib guice-3.0/extensions/jmx/build.properties0000644000175000017500000000013711461376774020577 0ustar drazzibdrazziblib.dir=../../lib src.dir=src test.dir=test build.dir=build module=com.google.inject.tools.jmx guice-3.0/extensions/jmx/test/0000755000175000017500000000000011214265014016314 5ustar drazzibdrazzibguice-3.0/extensions/jmx/test/com/0000755000175000017500000000000011214265014017072 5ustar drazzibdrazzibguice-3.0/extensions/jmx/test/com/google/0000755000175000017500000000000011214265014020346 5ustar drazzibdrazzibguice-3.0/extensions/jmx/test/com/google/inject/0000755000175000017500000000000011214265014021622 5ustar drazzibdrazzibguice-3.0/extensions/jmx/test/com/google/inject/tools/0000755000175000017500000000000011214265014022762 5ustar drazzibdrazzibguice-3.0/extensions/jmx/test/com/google/inject/tools/jmx/0000755000175000017500000000000011214265014023560 5ustar drazzibdrazzibguice-3.0/extensions/jmx/test/com/google/inject/tools/jmx/JmxTest.java0000644000175000017500000000335711214265014026031 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.tools.jmx; import com.google.inject.AbstractModule; import com.google.inject.BindingAnnotation; import com.google.inject.Key; import com.google.inject.Singleton; import com.google.inject.name.Names; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * @author crazybob@google.com (Bob Lee) */ public class JmxTest { interface Foo {} static class FooImpl implements Foo {} @Singleton static class TransactionalFoo implements Foo {} static class Bar {} @BindingAnnotation @Retention(RUNTIME) @interface Transactional {} public static void main(String[] args) throws Exception { Manager.main(new String[] { TestModule.class.getName() }); } public static class TestModule extends AbstractModule { protected void configure() { bind(Foo.class).to(FooImpl.class); bind(Bar.class); bind(Foo.class) .annotatedWith(Transactional.class) .to(FooImpl.class); bindConstant().annotatedWith(Names.named("port")).to(8080); bind(Key.get(Object.class)).to(Key.get(Bar.class)); // install(new ServletModule()); } } } guice-3.0/extensions/jmx/src/0000755000175000017500000000000011214265014016124 5ustar drazzibdrazzibguice-3.0/extensions/jmx/src/com/0000755000175000017500000000000011214265014016702 5ustar drazzibdrazzibguice-3.0/extensions/jmx/src/com/google/0000755000175000017500000000000011214265014020156 5ustar drazzibdrazzibguice-3.0/extensions/jmx/src/com/google/inject/0000755000175000017500000000000011214265014021432 5ustar drazzibdrazzibguice-3.0/extensions/jmx/src/com/google/inject/tools/0000755000175000017500000000000011214265014022572 5ustar drazzibdrazzibguice-3.0/extensions/jmx/src/com/google/inject/tools/jmx/0000755000175000017500000000000011214265014023370 5ustar drazzibdrazzibguice-3.0/extensions/jmx/src/com/google/inject/tools/jmx/package-info.java0000644000175000017500000000130711461123646026570 0ustar drazzibdrazzib/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * JMX integration; this extension requires {@code guice-jmx-3.0.jar}. */ package com.google.inject.tools.jmx;guice-3.0/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBinding.java0000644000175000017500000000203511214265014027062 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.tools.jmx; import com.google.inject.Binding; class ManagedBinding implements ManagedBindingMBean { final Binding binding; ManagedBinding(Binding binding) { this.binding = binding; } public String getSource() { return binding.getSource().toString(); } public String getKey() { return binding.getKey().toString(); } public String getProvider() { return binding.getProvider().toString(); } } guice-3.0/extensions/jmx/src/com/google/inject/tools/jmx/Manager.java0000644000175000017500000000712211214265014025607 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.tools.jmx; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import java.lang.annotation.Annotation; import java.lang.management.ManagementFactory; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; /** * Provides a JMX interface to Guice. * * @author crazybob@google.com (Bob Lee) */ public class Manager { /** * Registers all the bindings of an Injector with the platform MBean server. * Consider using the name of your root {@link Module} class as the domain. */ public static void manage( String domain, Injector injector) { manage(ManagementFactory.getPlatformMBeanServer(), domain, injector); } /** * Registers all the bindings of an Injector with the given MBean server. * Consider using the name of your root {@link Module} class as the domain. */ public static void manage(MBeanServer server, String domain, Injector injector) { // Register each binding independently. for (Binding binding : injector.getBindings().values()) { // Construct the name manually so we can ensure proper ordering of the // key/value pairs. StringBuilder name = new StringBuilder(); name.append(domain).append(":"); Key key = binding.getKey(); name.append("type=").append(quote(key.getTypeLiteral().toString())); Annotation annotation = key.getAnnotation(); if (annotation != null) { name.append(",annotation=").append(quote(annotation.toString())); } else { Class annotationType = key.getAnnotationType(); if (annotationType != null) { name.append(",annotation=") .append(quote("@" + annotationType.getName())); } } try { server.registerMBean(new ManagedBinding(binding), new ObjectName(name.toString())); } catch (MalformedObjectNameException e) { throw new RuntimeException("Bad object name: " + name.toString(), e); } catch (Exception e) { throw new RuntimeException(e); } } } static String quote(String value) { // JMX seems to have a comma bug. return ObjectName.quote(value).replace(',', ';'); } /** * Run with no arguments for usage instructions. */ public static void main(String[] args) throws Exception { if (args.length != 1) { System.err.println("Usage: java -Dcom.sun.management.jmxremote " + Manager.class.getName() + " [module class name]"); System.err.println("Then run 'jconsole' to connect."); System.exit(1); } Module module = (Module) Class.forName(args[0]).newInstance(); Injector injector = Guice.createInjector(module); manage(args[0], injector); System.out.println("Press Ctrl+C to exit..."); // Sleep forever. Thread.sleep(Long.MAX_VALUE); } } guice-3.0/extensions/jmx/src/com/google/inject/tools/jmx/ManagedBindingMBean.java0000644000175000017500000000172611214265014027773 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.tools.jmx; /** * JMX interface to bindings. * * @author crazybob@google.com (Bob Lee) */ public interface ManagedBindingMBean { /** * Gets the source of this binding. */ String getSource(); /** * Gets the provider to which this binding is bound. */ String getProvider(); /** * Gets the binding key. */ String getKey(); } guice-3.0/extensions/multibindings/0000755000175000017500000000000011542727754017431 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/build/0000755000175000017500000000000011542727756020532 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/build/META-INF/0000755000175000017500000000000011542727756021672 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/build/META-INF/MANIFEST.MF0000644000175000017500000000122311542727754023320 0ustar drazzibdrazzibManifest-Version: 1.0 Export-Package: com.google.inject.multibindings;version="1.3" Bundle-Name: guice-multibindings Created-By: 1.6.0_23 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-Copyright: Copyright (C) 2006 Google Inc. Bundle-Vendor: Google, Inc. Fragment-Host: com.google.inject Bundle-Version: 3.0 Bundle-ManifestVersion: 2 Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-Description: Guice is a lightweight dependency injection framew ork for Java 5 and above Bundle-DocURL: http://code.google.com/p/google-guice/ Bundle-SymbolicName: com.google.inject.multibindings guice-3.0/extensions/multibindings/build/dist/0000755000175000017500000000000011542727754021473 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/build/classes/0000755000175000017500000000000011542727754022165 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/build/classes/com/0000755000175000017500000000000011542727754022743 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/build/classes/com/google/0000755000175000017500000000000011542727754024217 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/build/classes/com/google/inject/0000755000175000017500000000000011542727754025473 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/build/classes/com/google/inject/multibindings/0000755000175000017500000000000011542727754030343 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/pom.xml0000644000175000017500000000107411460132762020734 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-multibindings Google Guice - Extensions - MultiBindings guice-3.0/extensions/multibindings/build.xml0000644000175000017500000000125011461503354021234 0ustar drazzibdrazzib guice-3.0/extensions/multibindings/build.properties0000644000175000017500000000024511461376774022651 0ustar drazzibdrazziblib.dir=../../lib src.dir=src test.dir=test build.dir=build test.class=com.google.inject.multibindings.AllTests module=com.google.inject.multibindings fragment=true guice-3.0/extensions/multibindings/test/0000755000175000017500000000000011214265006020367 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/test/com/0000755000175000017500000000000011214265006021145 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/test/com/google/0000755000175000017500000000000011214265006022421 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/test/com/google/inject/0000755000175000017500000000000011214265006023675 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/test/com/google/inject/multibindings/0000755000175000017500000000000011445110332026542 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java0000644000175000017500000006666411501231036032126 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import static com.google.inject.Asserts.assertContains; import static com.google.inject.multibindings.SpiUtils.assertMapVisitor; import static com.google.inject.multibindings.SpiUtils.instance; import static com.google.inject.multibindings.SpiUtils.providerInstance; import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH; import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE; import static com.google.inject.name.Names.named; import static java.lang.annotation.RetentionPolicy.RUNTIME; import com.google.inject.AbstractModule; import com.google.inject.Binding; import com.google.inject.BindingAnnotation; import com.google.inject.ConfigurationException; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.Stage; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Maps; import com.google.inject.name.Names; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.util.Modules; import com.google.inject.util.Providers; import junit.framework.TestCase; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * @author dpb@google.com (David P. Baker) */ public class MapBinderTest extends TestCase { final TypeLiteral> mapOfString = new TypeLiteral>() {}; final TypeLiteral> mapOfInteger = new TypeLiteral>() {}; final TypeLiteral>> mapOfSetOfString = new TypeLiteral>>() {}; private final TypeLiteral stringType = TypeLiteral.get(String.class); private final TypeLiteral intType = TypeLiteral.get(Integer.class); private final TypeLiteral> stringSetType = new TypeLiteral>() {}; public void testMapBinderAggregatesMultipleModules() { Module abc = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class); multibinder.addBinding("a").toInstance("A"); multibinder.addBinding("b").toInstance("B"); multibinder.addBinding("c").toInstance("C"); } }; Module de = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class); multibinder.addBinding("d").toInstance("D"); multibinder.addBinding("e").toInstance("E"); } }; Injector injector = Guice.createInjector(abc, de); Map abcde = injector.getInstance(Key.get(mapOfString)); assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E"), abcde); assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abc, de), BOTH, false, 0, instance("a", "A"), instance("b", "B"), instance("c", "C"), instance("d", "D"), instance("e", "E")); } public void testMapBinderAggregationForAnnotationInstance() { Module module = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class, Names.named("abc")); multibinder.addBinding("a").toInstance("A"); multibinder.addBinding("b").toInstance("B"); multibinder = MapBinder.newMapBinder( binder(), String.class, String.class, Names.named("abc")); multibinder.addBinding("c").toInstance("C"); } }; Injector injector = Guice.createInjector(module); Key> key = Key.get(mapOfString, Names.named("abc")); Map abc = injector.getInstance(key); assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); assertMapVisitor(key, stringType, stringType, setOf(module), BOTH, false, 0, instance("a", "A"), instance("b", "B"), instance("c", "C")); } public void testMapBinderAggregationForAnnotationType() { Module module = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class, Abc.class); multibinder.addBinding("a").toInstance("A"); multibinder.addBinding("b").toInstance("B"); multibinder = MapBinder.newMapBinder( binder(), String.class, String.class, Abc.class); multibinder.addBinding("c").toInstance("C"); } }; Injector injector = Guice.createInjector(module); Key> key = Key.get(mapOfString, Abc.class); Map abc = injector.getInstance(key); assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); assertMapVisitor(key, stringType, stringType, setOf(module), BOTH, false, 0, instance("a", "A"), instance("b", "B"), instance("c", "C")); } public void testMapBinderWithMultipleAnnotationValueSets() { Module module = new AbstractModule() { @Override protected void configure() { MapBinder abcMapBinder = MapBinder.newMapBinder( binder(), String.class, String.class, named("abc")); abcMapBinder.addBinding("a").toInstance("A"); abcMapBinder.addBinding("b").toInstance("B"); abcMapBinder.addBinding("c").toInstance("C"); MapBinder deMapBinder = MapBinder.newMapBinder( binder(), String.class, String.class, named("de")); deMapBinder.addBinding("d").toInstance("D"); deMapBinder.addBinding("e").toInstance("E"); } }; Injector injector = Guice.createInjector(module); Key> abcKey = Key.get(mapOfString, named("abc")); Map abc = injector.getInstance(abcKey); Key> deKey = Key.get(mapOfString, named("de")); Map de = injector.getInstance(deKey); assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); assertEquals(mapOf("d", "D", "e", "E"), de); assertMapVisitor(abcKey, stringType, stringType, setOf(module), BOTH, false, 1, instance("a", "A"), instance("b", "B"), instance("c", "C")); assertMapVisitor(deKey, stringType, stringType, setOf(module), BOTH, false, 1, instance("d", "D"), instance("e", "E")); } public void testMapBinderWithMultipleAnnotationTypeSets() { Module module = new AbstractModule() { @Override protected void configure() { MapBinder abcMapBinder = MapBinder.newMapBinder( binder(), String.class, String.class, Abc.class); abcMapBinder.addBinding("a").toInstance("A"); abcMapBinder.addBinding("b").toInstance("B"); abcMapBinder.addBinding("c").toInstance("C"); MapBinder deMapBinder = MapBinder.newMapBinder( binder(), String.class, String.class, De.class); deMapBinder.addBinding("d").toInstance("D"); deMapBinder.addBinding("e").toInstance("E"); } }; Injector injector = Guice.createInjector(module); Key> abcKey = Key.get(mapOfString, Abc.class); Map abc = injector.getInstance(abcKey); Key> deKey = Key.get(mapOfString, De.class); Map de = injector.getInstance(deKey); assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc); assertEquals(mapOf("d", "D", "e", "E"), de); assertMapVisitor(abcKey, stringType, stringType, setOf(module), BOTH, false, 1, instance("a", "A"), instance("b", "B"), instance("c", "C")); assertMapVisitor(deKey, stringType, stringType, setOf(module), BOTH, false, 1, instance("d", "D"), instance("e", "E")); } public void testMapBinderWithMultipleTypes() { Module module = new AbstractModule() { @Override protected void configure() { MapBinder.newMapBinder(binder(), String.class, String.class) .addBinding("a").toInstance("A"); MapBinder.newMapBinder(binder(), String.class, Integer.class) .addBinding("1").toInstance(1); } }; Injector injector = Guice.createInjector(module); assertEquals(mapOf("a", "A"), injector.getInstance(Key.get(mapOfString))); assertEquals(mapOf("1", 1), injector.getInstance(Key.get(mapOfInteger))); assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 1, instance("a", "A")); assertMapVisitor(Key.get(mapOfInteger), stringType, intType, setOf(module), BOTH, false, 1, instance("1", 1)); } public void testMapBinderWithEmptyMap() { Module module = new AbstractModule() { @Override protected void configure() { MapBinder.newMapBinder(binder(), String.class, String.class); } }; Injector injector = Guice.createInjector(module); Map map = injector.getInstance(Key.get(mapOfString)); assertEquals(Collections.emptyMap(), map); assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 0); } public void testMapBinderMapIsUnmodifiable() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { MapBinder.newMapBinder(binder(), String.class, String.class) .addBinding("a").toInstance("A"); } }); Map map = injector.getInstance(Key.get(mapOfString)); try { map.clear(); fail(); } catch(UnsupportedOperationException expected) { } } public void testMapBinderMapIsLazy() { Module module = new AbstractModule() { @Override protected void configure() { MapBinder.newMapBinder(binder(), String.class, Integer.class) .addBinding("num").toProvider(new Provider() { int nextValue = 1; public Integer get() { return nextValue++; } }); } }; Injector injector = Guice.createInjector(module); assertEquals(mapOf("num", 1), injector.getInstance(Key.get(mapOfInteger))); assertEquals(mapOf("num", 2), injector.getInstance(Key.get(mapOfInteger))); assertEquals(mapOf("num", 3), injector.getInstance(Key.get(mapOfInteger))); assertMapVisitor(Key.get(mapOfInteger), stringType, intType, setOf(module), BOTH, false, 0, providerInstance("num", 1)); } public void testMapBinderMapForbidsDuplicateKeys() { Module module = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class); multibinder.addBinding("a").toInstance("A"); multibinder.addBinding("a").toInstance("B"); } }; try { Guice.createInjector(module); fail(); } catch(CreationException expected) { assertContains(expected.getMessage(), "Map injection failed due to duplicated key \"a\""); } assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), MODULE, false, 0, instance("a", "A"), instance("a", "B")); } public void testMapBinderMapPermitDuplicateElements() { Module ab = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class); multibinder.addBinding("a").toInstance("A"); multibinder.addBinding("b").toInstance("B"); } }; Module bc = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class); multibinder.addBinding("b").toInstance("B"); multibinder.addBinding("c").toInstance("C"); multibinder.permitDuplicates(); } }; Injector injector = Guice.createInjector(ab, bc); assertEquals(mapOf("a", "A", "b", "B", "c", "C"), injector.getInstance(Key.get(mapOfString))); assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(ab, bc), BOTH, true, 0, instance("a", "A"), instance("b", "B"), instance("b", "B"), instance("c", "C")); } public void testMapBinderMultimap() { AbstractModule ab1c = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class); multibinder.addBinding("a").toInstance("A"); multibinder.addBinding("b").toInstance("B1"); multibinder.addBinding("c").toInstance("C"); } }; AbstractModule b2c = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class); multibinder.addBinding("b").toInstance("B2"); multibinder.addBinding("c").toInstance("C"); multibinder.permitDuplicates(); } }; Injector injector = Guice.createInjector(ab1c, b2c); assertEquals(mapOf("a", setOf("A"), "b", setOf("B1", "B2"), "c", setOf("C")), injector.getInstance(Key.get(mapOfSetOfString))); assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(ab1c, b2c), BOTH, true, 0, instance("a", "A"), instance("b", "B1"), instance("b", "B2"), instance("c", "C"), instance("c", "C")); } public void testMapBinderMultimapWithAnotation() { AbstractModule ab1 = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class, Abc.class); multibinder.addBinding("a").toInstance("A"); multibinder.addBinding("b").toInstance("B1"); } }; AbstractModule b2c = new AbstractModule() { @Override protected void configure() { MapBinder multibinder = MapBinder.newMapBinder( binder(), String.class, String.class, Abc.class); multibinder.addBinding("b").toInstance("B2"); multibinder.addBinding("c").toInstance("C"); multibinder.permitDuplicates(); } }; Injector injector = Guice.createInjector(ab1, b2c); assertEquals(mapOf("a", setOf("A"), "b", setOf("B1", "B2"), "c", setOf("C")), injector.getInstance(Key.get(mapOfSetOfString, Abc.class))); try { injector.getInstance(Key.get(mapOfSetOfString)); fail(); } catch (ConfigurationException expected) {} assertMapVisitor(Key.get(mapOfString, Abc.class), stringType, stringType, setOf(ab1, b2c), BOTH, true, 0, instance("a", "A"), instance("b", "B1"), instance("b", "B2"), instance("c", "C")); } public void testMapBinderMultimapIsUnmodifiable() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { MapBinder mapBinder = MapBinder.newMapBinder( binder(), String.class, String.class); mapBinder.addBinding("a").toInstance("A"); mapBinder.permitDuplicates(); } }); Map> map = injector.getInstance(Key.get(mapOfSetOfString)); try { map.clear(); fail(); } catch(UnsupportedOperationException expected) { } try { map.get("a").clear(); fail(); } catch(UnsupportedOperationException expected) { } } public void testMapBinderMapForbidsNullKeys() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { MapBinder.newMapBinder(binder(), String.class, String.class).addBinding(null); } }); fail(); } catch (CreationException expected) {} } public void testMapBinderMapForbidsNullValues() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { MapBinder.newMapBinder(binder(), String.class, String.class) .addBinding("null").toProvider(Providers.of(null)); } }); try { injector.getInstance(Key.get(mapOfString)); fail(); } catch(ProvisionException expected) { assertContains(expected.getMessage(), "1) Map injection failed due to null value for key \"null\""); } } public void testMapBinderProviderIsScoped() { final Provider counter = new Provider() { int next = 1; public Integer get() { return next++; } }; Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { MapBinder.newMapBinder(binder(), String.class, Integer.class) .addBinding("one").toProvider(counter).asEagerSingleton(); } }); assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one")); assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one")); } public void testSourceLinesInMapBindings() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { MapBinder.newMapBinder(binder(), String.class, Integer.class) .addBinding("one"); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) No implementation for java.lang.Integer", "at " + getClass().getName()); } } /** We just want to make sure that mapbinder's binding depends on the underlying multibinder. */ public void testMultibinderDependencies() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { MapBinder mapBinder = MapBinder.newMapBinder(binder(), Integer.class, String.class); mapBinder.addBinding(1).toInstance("A"); mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b"))); bindConstant().annotatedWith(Names.named("b")).to("B"); } }); Binding> binding = injector.getBinding(new Key>() {}); HasDependencies withDependencies = (HasDependencies) binding; Key setKey = new Key>>>() {}; assertEquals(ImmutableSet.>of(Dependency.get(setKey)), withDependencies.getDependencies()); } /** We just want to make sure that mapbinder's binding depends on the underlying multibinder. */ public void testMultibinderDependenciesInToolStage() { Injector injector = Guice.createInjector(Stage.TOOL, new AbstractModule() { protected void configure() { MapBinder mapBinder = MapBinder.newMapBinder(binder(), Integer.class, String.class); mapBinder.addBinding(1).toInstance("A"); mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b"))); bindConstant().annotatedWith(Names.named("b")).to("B"); }}); Binding> binding = injector.getBinding(new Key>() {}); HasDependencies withDependencies = (HasDependencies) binding; Key setKey = new Key>>>() {}; assertEquals(ImmutableSet.>of(Dependency.get(setKey)), withDependencies.getDependencies()); } /** * Our implementation maintains order, but doesn't guarantee it in the API spec. * TODO: specify the iteration order? */ public void testBindOrderEqualsIterationOrder() { Injector injector = Guice.createInjector( new AbstractModule() { protected void configure() { MapBinder mapBinder = MapBinder.newMapBinder(binder(), String.class, String.class); mapBinder.addBinding("leonardo").toInstance("blue"); mapBinder.addBinding("donatello").toInstance("purple"); install(new AbstractModule() { protected void configure() { MapBinder.newMapBinder(binder(), String.class, String.class) .addBinding("michaelangelo").toInstance("orange"); } }); } }, new AbstractModule() { protected void configure() { MapBinder.newMapBinder(binder(), String.class, String.class) .addBinding("raphael").toInstance("red"); } }); Map map = injector.getInstance(new Key>() {}); Iterator> iterator = map.entrySet().iterator(); assertEquals(Maps.immutableEntry("leonardo", "blue"), iterator.next()); assertEquals(Maps.immutableEntry("donatello", "purple"), iterator.next()); assertEquals(Maps.immutableEntry("michaelangelo", "orange"), iterator.next()); assertEquals(Maps.immutableEntry("raphael", "red"), iterator.next()); } /** * With overrides, we should get the union of all map bindings. */ public void testModuleOverrideAndMapBindings() { Module ab = new AbstractModule() { protected void configure() { MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); multibinder.addBinding("a").toInstance("A"); multibinder.addBinding("b").toInstance("B"); } }; Module cd = new AbstractModule() { protected void configure() { MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); multibinder.addBinding("c").toInstance("C"); multibinder.addBinding("d").toInstance("D"); } }; Module ef = new AbstractModule() { protected void configure() { MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); multibinder.addBinding("e").toInstance("E"); multibinder.addBinding("f").toInstance("F"); } }; Module abcd = Modules.override(ab).with(cd); Injector injector = Guice.createInjector(abcd, ef); assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"), injector.getInstance(Key.get(mapOfString))); assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abcd, ef), BOTH, false, 0, instance("a", "A"), instance("b", "B"), instance("c", "C"), instance("d", "D"), instance( "e", "E"), instance("f", "F")); } /** * With overrides, we should get the union of all map bindings. */ public void testModuleOverrideAndMapBindingsWithPermitDuplicates() { Module abc = new AbstractModule() { protected void configure() { MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); multibinder.addBinding("a").toInstance("A"); multibinder.addBinding("b").toInstance("B"); multibinder.addBinding("c").toInstance("C"); multibinder.permitDuplicates(); } }; Module cd = new AbstractModule() { protected void configure() { MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); multibinder.addBinding("c").toInstance("C"); multibinder.addBinding("d").toInstance("D"); multibinder.permitDuplicates(); } }; Module ef = new AbstractModule() { protected void configure() { MapBinder multibinder = MapBinder.newMapBinder(binder(), String.class, String.class); multibinder.addBinding("e").toInstance("E"); multibinder.addBinding("f").toInstance("F"); multibinder.permitDuplicates(); } }; Module abcd = Modules.override(abc).with(cd); Injector injector = Guice.createInjector(abcd, ef); assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"), injector.getInstance(Key.get(mapOfString))); assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abcd, ef), BOTH, true, 0, instance("a", "A"), instance("b", "B"), instance("c", "C"), instance("c", "C"), instance( "d", "D"), instance("e", "E"), instance("f", "F")); } @Retention(RUNTIME) @BindingAnnotation @interface Abc {} @Retention(RUNTIME) @BindingAnnotation @interface De {} @SuppressWarnings("unchecked") private Map mapOf(Object... elements) { Map result = new HashMap(); for (int i = 0; i < elements.length; i += 2) { result.put((K)elements[i], (V)elements[i+1]); } return result; } @SuppressWarnings("unchecked") private Set setOf(V... elements) { return new HashSet(Arrays.asList(elements)); } @BindingAnnotation @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) private static @interface Marker {} @Marker public void testMapBinderMatching() throws Exception { Method m = MapBinderTest.class.getDeclaredMethod("testMapBinderMatching"); assertNotNull(m); final Annotation marker = m.getAnnotation(Marker.class); Injector injector = Guice.createInjector(new AbstractModule() { @Override public void configure() { MapBinder mb1 = MapBinder.newMapBinder(binder(), Integer.class, Integer.class, Marker.class); MapBinder mb2 = MapBinder.newMapBinder(binder(), Integer.class, Integer.class, marker); mb1.addBinding(1).toInstance(1); mb2.addBinding(2).toInstance(2); // This assures us that the two binders are equivalent, so we expect the instance added to // each to have been added to one set. assertEquals(mb1, mb2); } }); TypeLiteral> t = new TypeLiteral>() {}; Map s1 = injector.getInstance(Key.get(t, Marker.class)); Map s2 = injector.getInstance(Key.get(t, marker)); // This assures us that the two sets are in fact equal. They may not be same set (as in Java // object identical), but we shouldn't expect that, since probably Guice creates the set each // time in case the elements are dependent on scope. assertEquals(s1, s2); // This ensures that MultiBinder is internally using the correct set name -- // making sure that instances of marker annotations have the same set name as // MarkerAnnotation.class. Map expected = new HashMap(); expected.put(1, 1); expected.put(2, 2); assertEquals(expected, s1); } } guice-3.0/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java0000644000175000017500000005407611445360024031202 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import static com.google.inject.multibindings.MapBinder.entryOfProviderOf; import static com.google.inject.multibindings.MapBinder.mapOf; import static com.google.inject.multibindings.MapBinder.mapOfProviderOf; import static com.google.inject.multibindings.MapBinder.mapOfSetOfProviderOf; import static com.google.inject.multibindings.Multibinder.setOf; import static com.google.inject.multibindings.SpiUtils.BindType.INSTANCE; import static com.google.inject.multibindings.SpiUtils.BindType.LINKED; import static com.google.inject.multibindings.SpiUtils.BindType.PROVIDER_INSTANCE; import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH; import static com.google.inject.multibindings.SpiUtils.VisitType.INJECTOR; import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Lists; import com.google.inject.spi.DefaultBindingTargetVisitor; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; import com.google.inject.spi.InstanceBinding; import com.google.inject.spi.LinkedKeyBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderLookup; /** * Utilities for testing the Multibinder & MapBinder extension SPI. * * @author sameb@google.com (Sam Berlin) */ public class SpiUtils { /** The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. */ enum VisitType { INJECTOR, MODULE, BOTH } /** * Asserts that MapBinderBinding visitors for work correctly. * * @param The type of the binding * @param mapKey The key the map belongs to. * @param keyType the TypeLiteral of the key of the map * @param valueType the TypeLiteral of the value of the map * @param modules The modules that define the mapbindings * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. * @param allowDuplicates If duplicates are allowed. * @param expectedMapBindings The number of other mapbinders we expect to see. * @param results The kind of bindings contained in the mapbinder. */ static void assertMapVisitor(Key mapKey, TypeLiteral keyType, TypeLiteral valueType, Iterable modules, VisitType visitType, boolean allowDuplicates, int expectedMapBindings, MapResult... results) { if(visitType == null) { fail("must test something"); } if (visitType == BOTH || visitType == INJECTOR) { mapInjectorTest(mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings, results); } if (visitType == BOTH || visitType == MODULE) { mapModuleTest(mapKey, keyType, valueType, modules, allowDuplicates, expectedMapBindings, results); } } @SuppressWarnings("unchecked") private static void mapInjectorTest(Key mapKey, TypeLiteral keyType, TypeLiteral valueType, Iterable modules, boolean allowDuplicates, int expectedMapBindings, MapResult... results) { Injector injector = Guice.createInjector(modules); Visitor visitor = new Visitor(); Binding mapBinding = injector.getBinding(mapKey); MapBinderBinding mapbinder = (MapBinderBinding)mapBinding.acceptTargetVisitor(visitor); assertNotNull(mapbinder); assertEquals(keyType, mapbinder.getKeyTypeLiteral()); assertEquals(valueType, mapbinder.getValueTypeLiteral()); assertEquals(allowDuplicates, mapbinder.permitsDuplicates()); List>> entries = Lists.newArrayList(mapbinder.getEntries()); List mapResults = Lists.newArrayList(results); assertEquals("wrong entries, expected: " + mapResults + ", but was: " + entries, mapResults.size(), entries.size()); for(MapResult result : mapResults) { Map.Entry> found = null; for(Map.Entry> entry : entries) { Object key = entry.getKey(); Binding value = entry.getValue(); if(!key.equals(result.k)) { continue; } switch (result.v.type) { case INSTANCE: if (value instanceof InstanceBinding && ((InstanceBinding) value).getInstance().equals(result.v.instance)) { found = entry; } break; case LINKED: if (value instanceof LinkedKeyBinding && ((LinkedKeyBinding) value).getKey().equals(result.v.key)) { found = entry; } break; case PROVIDER_INSTANCE: if (value instanceof ProviderInstanceBinding && ((ProviderInstanceBinding) value).getProviderInstance().get().equals( result.v.instance)) { found = entry; } break; } } if(found == null) { fail("Could not find entry: " + result + " in remaining entries: " + entries); } else { assertTrue(mapbinder.containsElement(found.getValue())); entries.remove(found); } } if(!entries.isEmpty()) { fail("Found all entries of: " + mapResults + ", but more were left over: " + entries); } Key mapOfProvider = adapt(mapKey, mapOfProviderOf(keyType, valueType)); Key mapOfSetOfProvider = adapt(mapKey, mapOfSetOfProviderOf(keyType, valueType)); Key mapOfSet = adapt(mapKey, mapOf(keyType, setOf(valueType))); Key setOfEntry = adapt(mapKey, setOf(entryOfProviderOf(keyType, valueType))); boolean entrySetMatch = false; boolean mapProviderMatch = false; boolean mapSetMatch = false; boolean mapSetProviderMatch = false; List otherMapBindings = Lists.newArrayList(); List otherMatches = Lists.newArrayList(); for(Binding b : injector.getAllBindings().values()) { boolean contains = mapbinder.containsElement(b); Object visited = b.acceptTargetVisitor(visitor); if(visited instanceof MapBinderBinding) { if(visited.equals(mapbinder)) { assertTrue(contains); } else { otherMapBindings.add(visited); } } else if(b.getKey().equals(mapOfProvider)) { assertTrue(contains); mapProviderMatch = true; } else if(b.getKey().equals(mapOfSet)) { assertTrue(contains); mapSetMatch = true; } else if(b.getKey().equals(mapOfSetOfProvider)) { assertTrue(contains); mapSetProviderMatch = true; } else if(b.getKey().equals(setOfEntry)) { assertTrue(contains); entrySetMatch = true; // Validate that this binding is also a MultibinderBinding. assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding); } else if (contains) { otherMatches.add(b); } } int sizeOfOther = otherMatches.size(); if(allowDuplicates) { sizeOfOther--; // account for 1 duplicate binding } sizeOfOther = sizeOfOther / 2; // account for 1 value & 1 Map.Entry of each expected binding. assertEquals("Incorrect other matches: " + otherMatches, mapResults.size(), sizeOfOther); assertTrue(entrySetMatch); assertTrue(mapProviderMatch); assertEquals(allowDuplicates, mapSetMatch); assertEquals(allowDuplicates, mapSetProviderMatch); assertEquals("other MapBindings found: " + otherMapBindings, expectedMapBindings, otherMapBindings.size()); } /** Adapts a key, keeping the original annotation, using the new type literal. */ private static Key adapt(Key mapKey, TypeLiteral resultType) { if(mapKey.getAnnotation() != null) { return Key.get(resultType, mapKey.getAnnotation()); } else if(mapKey.getAnnotationType() != null) { return Key.get(resultType, mapKey.getAnnotationType()); } else { return Key.get(resultType); } } @SuppressWarnings("unchecked") private static void mapModuleTest(Key mapKey, TypeLiteral keyType, TypeLiteral valueType, Iterable modules, boolean allowDuplicates, int expectedMapBindings, MapResult... results) { List elements = Elements.getElements(modules); Visitor visitor = new Visitor(); MapBinderBinding mapbinder = null; for(Element element : elements) { if(element instanceof Binding && ((Binding)element).getKey().equals(mapKey)) { mapbinder = (MapBinderBinding)((Binding)element).acceptTargetVisitor(visitor); break; } } assertNotNull(mapbinder); assertEquals(keyType, mapbinder.getKeyTypeLiteral()); assertEquals(valueType, mapbinder.getValueTypeLiteral()); List mapResults = Lists.newArrayList(results); Key mapOfProvider = adapt(mapKey, mapOfProviderOf(keyType, valueType)); Key mapOfSetOfProvider = adapt(mapKey, mapOfSetOfProviderOf(keyType, valueType)); Key mapOfSet = adapt(mapKey, mapOf(keyType, setOf(valueType))); Key setOfEntry = adapt(mapKey, setOf(entryOfProviderOf(keyType, valueType))); boolean entrySetMatch = false; boolean mapProviderMatch = false; boolean mapSetMatch = false; boolean mapSetProviderMatch = false; List otherMapBindings = Lists.newArrayList(); List otherMatches = Lists.newArrayList(); List otherElements = Lists.newArrayList(); for(Element element : elements) { boolean contains = mapbinder.containsElement(element); if(!contains) { otherElements.add(element); } boolean matched = false; Key key = null; Binding b = null; if(element instanceof Binding) { b = (Binding)element; key = b.getKey(); Object visited = b.acceptTargetVisitor(visitor); if(visited instanceof MapBinderBinding) { matched = true; if(visited.equals(mapbinder)) { assertTrue(contains); } else { otherMapBindings.add(visited); } } } else if(element instanceof ProviderLookup) { key = ((ProviderLookup)element).getKey(); } if(!matched && key != null) { if(key.equals(mapOfProvider)) { matched = true; assertTrue(contains); mapProviderMatch = true; } else if(key.equals(mapOfSet)) { matched = true; assertTrue(contains); mapSetMatch = true; } else if(key.equals(mapOfSetOfProvider)) { matched = true; assertTrue(contains); mapSetProviderMatch = true; } else if(key.equals(setOfEntry)) { matched = true; assertTrue(contains); entrySetMatch = true; // Validate that this binding is also a MultibinderBinding. if(b != null) { assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding); } } } if(!matched && contains) { otherMatches.add(element); } } int otherMatchesSize = otherMatches.size(); if(allowDuplicates) { otherMatchesSize--; // allow for 1 duplicate binding } otherMatchesSize = otherMatchesSize / 3; // value, ProviderLookup per value, Map.Entry per value assertEquals("incorrect number of contains, leftover matches: " + otherMatches, mapResults .size(), otherMatchesSize); assertTrue(entrySetMatch); assertTrue(mapProviderMatch); assertEquals(allowDuplicates, mapSetMatch); assertEquals(allowDuplicates, mapSetProviderMatch); assertEquals("other MapBindings found: " + otherMapBindings, expectedMapBindings, otherMapBindings.size()); // Validate that we can construct an injector out of the remaining bindings. Guice.createInjector(Elements.getModule(otherElements)); } /** * Asserts that MultibinderBinding visitors work correctly. * * @param The type of the binding * @param setKey The key the set belongs to. * @param elementType the TypeLiteral of the element * @param modules The modules that define the multibindings * @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both. * @param allowDuplicates If duplicates are allowed. * @param expectedMultibindings The number of other multibinders we expect to see. * @param results The kind of bindings contained in the multibinder. */ static void assertSetVisitor(Key setKey, TypeLiteral elementType, Iterable modules, VisitType visitType, boolean allowDuplicates, int expectedMultibindings, BindResult... results) { if(visitType == null) { fail("must test something"); } if(visitType == BOTH || visitType == INJECTOR) { setInjectorTest(setKey, elementType, modules, allowDuplicates, expectedMultibindings, results); } if(visitType == BOTH || visitType == MODULE) { setModuleTest(setKey, elementType, modules, allowDuplicates, expectedMultibindings, results); } } @SuppressWarnings("unchecked") private static void setInjectorTest(Key setKey, TypeLiteral elementType, Iterable modules, boolean allowDuplicates, int otherMultibindings, BindResult... results) { Injector injector = Guice.createInjector(modules); Visitor visitor = new Visitor(); Binding binding = injector.getBinding(setKey); MultibinderBinding multibinder = (MultibinderBinding)binding.acceptTargetVisitor(visitor); assertNotNull(multibinder); assertEquals(elementType, multibinder.getElementTypeLiteral()); assertEquals(allowDuplicates, multibinder.permitsDuplicates()); List> elements = Lists.newArrayList(multibinder.getElements()); List bindResults = Lists.newArrayList(results); assertEquals("wrong bind elements, expected: " + bindResults + ", but was: " + multibinder.getElements(), bindResults.size(), elements.size()); for(BindResult result : bindResults) { Binding found = null; for(Binding item : elements) { switch (result.type) { case INSTANCE: if (item instanceof InstanceBinding && ((InstanceBinding) item).getInstance().equals(result.instance)) { found = item; } break; case LINKED: if (item instanceof LinkedKeyBinding && ((LinkedKeyBinding) item).getKey().equals(result.key)) { found = item; } break; case PROVIDER_INSTANCE: if (item instanceof ProviderInstanceBinding && ((ProviderInstanceBinding) item).getProviderInstance().get().equals( result.instance)) { found = item; } break; } } if(found == null) { fail("Could not find element: " + result + " in remaining elements: " + elements); } else { elements.remove(found); } } if(!elements.isEmpty()) { fail("Found all elements of: " + bindResults + ", but more were left over: " + elements); } Set setOfElements = new HashSet(multibinder.getElements()); List otherMultibinders = Lists.newArrayList(); List otherContains = Lists.newArrayList(); for(Binding b : injector.getAllBindings().values()) { boolean contains = multibinder.containsElement(b); Object visited = b.acceptTargetVisitor(visitor); if(visited != null) { if(visited.equals(multibinder)) { assertTrue(contains); } else { otherMultibinders.add(visited); } } else if(setOfElements.contains(b)) { assertTrue(contains); } else if(contains) { otherContains.add(b); } } if(allowDuplicates) { assertEquals("contained more than it should: " + otherContains, 1, otherContains.size()); } else { assertTrue("contained more than it should: " + otherContains, otherContains.isEmpty()); } assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings, otherMultibinders.size()); } @SuppressWarnings("unchecked") private static void setModuleTest(Key setKey, TypeLiteral elementType, Iterable modules, boolean allowDuplicates, int otherMultibindings, BindResult... results) { List bindResults = Lists.newArrayList(results); List elements = Elements.getElements(modules); Visitor visitor = new Visitor(); MultibinderBinding multibinder = null; for(Element element : elements) { if(element instanceof Binding && ((Binding)element).getKey().equals(setKey)) { multibinder = (MultibinderBinding)((Binding)element).acceptTargetVisitor(visitor); break; } } assertNotNull(multibinder); assertEquals(elementType, multibinder.getElementTypeLiteral()); List otherMultibinders = Lists.newArrayList(); Set otherContains = new HashSet(); List otherElements = Lists.newArrayList(); for(Element element : elements) { boolean contains = multibinder.containsElement(element); if(!contains) { otherElements.add(element); } boolean matched = false; if(element instanceof Binding) { Binding binding = (Binding)element; Object visited = binding.acceptTargetVisitor(visitor); if(visited != null) { matched = true; if(visited.equals(multibinder)) { assertTrue(contains); } else { otherMultibinders.add(visited); } } } if(!matched && contains) { otherContains.add(element); } } if(allowDuplicates) { assertEquals("wrong contained elements: " + otherContains, bindResults.size() + 1, otherContains.size()); } else { assertEquals("wrong contained elements: " + otherContains, bindResults.size(), otherContains.size()); } assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings, otherMultibinders.size()); // Validate that we can construct an injector out of the remaining bindings. Guice.createInjector(Elements.getModule(otherElements)); } static MapResult instance(K k, V v) { return new MapResult(k, new BindResult(INSTANCE, v, null)); } static MapResult linked(K k, Class clazz) { return new MapResult(k, new BindResult(LINKED, null, Key.get(clazz))); } static MapResult linked(K k, Key key) { return new MapResult(k, new BindResult(LINKED, null, key)); } static MapResult providerInstance(K k, V v) { return new MapResult(k, new BindResult(PROVIDER_INSTANCE, v, null)); } private static class MapResult { private final K k; private final BindResult v; MapResult(K k, BindResult v) { this.k = k; this.v = v; } @Override public String toString() { return "entry[key[" + k + "],value[" + v + "]]"; } } static BindResult instance(T t) { return new BindResult(INSTANCE, t, null); } static BindResult linked(Class clazz) { return new BindResult(LINKED, null, Key.get(clazz)); } static BindResult linked(Key key) { return new BindResult(LINKED, null, key); } static BindResult providerInstance(T t) { return new BindResult(PROVIDER_INSTANCE, t, null); } /** The kind of binding. */ static enum BindType { INSTANCE, LINKED, PROVIDER_INSTANCE } /** The result of the binding. */ private static class BindResult { private final BindType type; private final Key key; private final T instance; private BindResult(BindType type, T instance, Key key) { this.type = type; this.instance = instance; this.key = key; } @Override public String toString() { switch(type) { case INSTANCE: return "instance[" + instance + "]"; case LINKED: return "linkedKey[" + key + "]"; case PROVIDER_INSTANCE: return "providerInstance[" + instance + "]"; } return null; } } private static class Visitor extends DefaultBindingTargetVisitor implements MultibindingsTargetVisitor { public Object visit(MultibinderBinding multibinding) { return multibinding; } public Object visit(MapBinderBinding mapbinding) { return mapbinding; } } } guice-3.0/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java0000644000175000017500000005751511501201120032525 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import static com.google.inject.Asserts.assertContains; import static com.google.inject.multibindings.SpiUtils.assertSetVisitor; import static com.google.inject.multibindings.SpiUtils.instance; import static com.google.inject.multibindings.SpiUtils.providerInstance; import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH; import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE; import static com.google.inject.name.Names.named; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import junit.framework.TestCase; import com.google.inject.AbstractModule; import com.google.inject.Binding; import com.google.inject.BindingAnnotation; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.Stage; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Sets; import com.google.inject.name.Names; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InstanceBinding; import com.google.inject.spi.LinkedKeyBinding; import com.google.inject.util.Modules; import com.google.inject.util.Providers; /** * @author jessewilson@google.com (Jesse Wilson) */ public class MultibinderTest extends TestCase { final TypeLiteral> setOfString = new TypeLiteral>() {}; final TypeLiteral> setOfInteger = new TypeLiteral>() {}; final TypeLiteral stringType = TypeLiteral.get(String.class); final TypeLiteral intType = TypeLiteral.get(Integer.class); public void testMultibinderAggregatesMultipleModules() { Module abc = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("A"); multibinder.addBinding().toInstance("B"); multibinder.addBinding().toInstance("C"); } }; Module de = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("D"); multibinder.addBinding().toInstance("E"); } }; Injector injector = Guice.createInjector(abc, de); Key> setKey = Key.get(setOfString); Set abcde = injector.getInstance(setKey); Set results = setOf("A", "B", "C", "D", "E"); assertEquals(results, abcde); assertSetVisitor(setKey, stringType, setOf(abc, de), BOTH, false, 0, instance("A"), instance("B"), instance("C"), instance("D"), instance("E")); } public void testMultibinderAggregationForAnnotationInstance() { Module module = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class, Names.named("abc")); multibinder.addBinding().toInstance("A"); multibinder.addBinding().toInstance("B"); multibinder = Multibinder.newSetBinder(binder(), String.class, Names.named("abc")); multibinder.addBinding().toInstance("C"); } }; Injector injector = Guice.createInjector(module); Key> setKey = Key.get(setOfString, Names.named("abc")); Set abc = injector.getInstance(setKey); Set results = setOf("A", "B", "C"); assertEquals(results, abc); assertSetVisitor(setKey, stringType, setOf(module), BOTH, false, 0, instance("A"), instance("B"), instance("C")); } public void testMultibinderAggregationForAnnotationType() { Module module = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class, Abc.class); multibinder.addBinding().toInstance("A"); multibinder.addBinding().toInstance("B"); multibinder = Multibinder.newSetBinder(binder(), String.class, Abc.class); multibinder.addBinding().toInstance("C"); } }; Injector injector = Guice.createInjector(module); Key> setKey = Key.get(setOfString, Abc.class); Set abcde = injector.getInstance(setKey); Set results = setOf("A", "B", "C"); assertEquals(results, abcde); assertSetVisitor(setKey, stringType, setOf(module), BOTH, false, 0, instance("A"), instance("B"), instance("C")); } public void testMultibinderWithMultipleAnnotationValueSets() { Module module = new AbstractModule() { protected void configure() { Multibinder abcMultibinder = Multibinder.newSetBinder(binder(), String.class, named("abc")); abcMultibinder.addBinding().toInstance("A"); abcMultibinder.addBinding().toInstance("B"); abcMultibinder.addBinding().toInstance("C"); Multibinder deMultibinder = Multibinder.newSetBinder(binder(), String.class, named("de")); deMultibinder.addBinding().toInstance("D"); deMultibinder.addBinding().toInstance("E"); } }; Injector injector = Guice.createInjector(module); Key> abcSetKey = Key.get(setOfString, named("abc")); Set abc = injector.getInstance(abcSetKey); Key> deSetKey = Key.get(setOfString, named("de")); Set de = injector.getInstance(deSetKey); Set abcResults = setOf("A", "B", "C"); assertEquals(abcResults, abc); Set deResults = setOf("D", "E"); assertEquals(deResults, de); assertSetVisitor(abcSetKey, stringType, setOf(module), BOTH, false, 1, instance("A"), instance("B"), instance("C")); assertSetVisitor(deSetKey, stringType, setOf(module), BOTH, false, 1, instance("D"), instance("E")); } public void testMultibinderWithMultipleAnnotationTypeSets() { Module module = new AbstractModule() { protected void configure() { Multibinder abcMultibinder = Multibinder.newSetBinder(binder(), String.class, Abc.class); abcMultibinder.addBinding().toInstance("A"); abcMultibinder.addBinding().toInstance("B"); abcMultibinder.addBinding().toInstance("C"); Multibinder deMultibinder = Multibinder.newSetBinder(binder(), String.class, De.class); deMultibinder.addBinding().toInstance("D"); deMultibinder.addBinding().toInstance("E"); } }; Injector injector = Guice.createInjector(module); Key> abcSetKey = Key.get(setOfString, Abc.class); Set abc = injector.getInstance(abcSetKey); Key> deSetKey = Key.get(setOfString, De.class); Set de = injector.getInstance(deSetKey); Set abcResults = setOf("A", "B", "C"); assertEquals(abcResults, abc); Set deResults = setOf("D", "E"); assertEquals(deResults, de); assertSetVisitor(abcSetKey, stringType, setOf(module), BOTH, false, 1, instance("A"), instance("B"), instance("C")); assertSetVisitor(deSetKey, stringType, setOf(module), BOTH, false, 1, instance("D"), instance("E")); } public void testMultibinderWithMultipleSetTypes() { Module module = new AbstractModule() { protected void configure() { Multibinder.newSetBinder(binder(), String.class) .addBinding().toInstance("A"); Multibinder.newSetBinder(binder(), Integer.class) .addBinding().toInstance(1); } }; Injector injector = Guice.createInjector(module); assertEquals(setOf("A"), injector.getInstance(Key.get(setOfString))); assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger))); assertSetVisitor(Key.get(setOfString), stringType, setOf(module), BOTH, false, 1, instance("A")); assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 1, instance(1)); } public void testMultibinderWithEmptySet() { Module module = new AbstractModule() { protected void configure() { Multibinder.newSetBinder(binder(), String.class); } }; Injector injector = Guice.createInjector(module); Set set = injector.getInstance(Key.get(setOfString)); assertEquals(Collections.emptySet(), set); assertSetVisitor(Key.get(setOfString), stringType, setOf(module), BOTH, false, 0); } public void testMultibinderSetIsUnmodifiable() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { Multibinder.newSetBinder(binder(), String.class) .addBinding().toInstance("A"); } }); Set set = injector.getInstance(Key.get(setOfString)); try { set.clear(); fail(); } catch(UnsupportedOperationException expected) { } } public void testMultibinderSetIsLazy() { Module module = new AbstractModule() { protected void configure() { Multibinder.newSetBinder(binder(), Integer.class) .addBinding().toProvider(new Provider() { int nextValue = 1; public Integer get() { return nextValue++; } }); } }; Injector injector = Guice.createInjector(module); assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger))); assertEquals(setOf(2), injector.getInstance(Key.get(setOfInteger))); assertEquals(setOf(3), injector.getInstance(Key.get(setOfInteger))); assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 0, providerInstance(1)); } public void testMultibinderSetForbidsDuplicateElements() { Module module = new AbstractModule() { protected void configure() { final Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("A"); multibinder.addBinding().toInstance("A"); } }; Injector injector = Guice.createInjector(module); try { injector.getInstance(Key.get(setOfString)); fail(); } catch(ProvisionException expected) { assertContains(expected.getMessage(), "1) Set injection failed due to duplicated element \"A\""); } // But we can still visit the module! assertSetVisitor(Key.get(setOfString), stringType, setOf(module), MODULE, false, 0, instance("A"), instance("A")); } public void testMultibinderSetPermitDuplicateElements() { Module ab = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("A"); multibinder.addBinding().toInstance("B"); } }; Module bc = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.permitDuplicates(); multibinder.addBinding().toInstance("B"); multibinder.addBinding().toInstance("C"); } }; Injector injector = Guice.createInjector(ab, bc); assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString))); assertSetVisitor(Key.get(setOfString), stringType, setOf(ab, bc), BOTH, true, 0, instance("A"), instance("B"), instance("B"), instance("C")); } public void testMultibinderSetPermitDuplicateCallsToPermitDuplicates() { Module ab = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.permitDuplicates(); multibinder.addBinding().toInstance("A"); multibinder.addBinding().toInstance("B"); } }; Module bc = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.permitDuplicates(); multibinder.addBinding().toInstance("B"); multibinder.addBinding().toInstance("C"); } }; Injector injector = Guice.createInjector(ab, bc); assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString))); assertSetVisitor(Key.get(setOfString), stringType, setOf(ab, bc), BOTH, true, 0, instance("A"), instance("B"), instance("B"), instance("C")); } public void testMultibinderSetForbidsNullElements() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { Multibinder.newSetBinder(binder(), String.class) .addBinding().toProvider(Providers.of(null)); } }); try { injector.getInstance(Key.get(setOfString)); fail(); } catch(ProvisionException expected) { assertContains(expected.getMessage(), "1) Set injection failed due to null element"); } } public void testSourceLinesInMultibindings() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { Multibinder.newSetBinder(binder(), Integer.class).addBinding(); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "No implementation for java.lang.Integer", "at " + getClass().getName()); } } /** * We just want to make sure that multibinder's binding depends on each of its values. We don't * really care about the underlying structure of those bindings, which are implementation details. */ public void testMultibinderDependencies() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("A"); multibinder.addBinding().to(Key.get(String.class, Names.named("b"))); bindConstant().annotatedWith(Names.named("b")).to("B"); } }); Binding> binding = injector.getBinding(new Key>() {}); HasDependencies withDependencies = (HasDependencies) binding; Set elements = Sets.newHashSet(); for (Dependency dependency : withDependencies.getDependencies()) { elements.add((String) injector.getInstance(dependency.getKey())); } assertEquals(ImmutableSet.of("A", "B"), elements); } /** * We just want to make sure that multibinder's binding depends on each of its values. We don't * really care about the underlying structure of those bindings, which are implementation details. */ public void testMultibinderDependenciesInToolStage() { Injector injector = Guice.createInjector(Stage.TOOL, new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("A"); multibinder.addBinding().to(Key.get(String.class, Names.named("b"))); bindConstant().annotatedWith(Names.named("b")).to("B"); }}); Binding> binding = injector.getBinding(new Key>() {}); HasDependencies withDependencies = (HasDependencies) binding; InstanceBinding instanceBinding = null; LinkedKeyBinding linkedBinding = null; // The non-tool stage test can test this by calling injector.getInstance to ensure // the right values are returned -- in tool stage we can't do that. It's also a // little difficult to validate the dependencies & bindings, because they're // bindings created internally within Multibinder. // To workaround this, we just validate that the dependencies lookup to a single // InstanceBinding whose value is "A" and another LinkedBinding whose target is // the Key of @Named("b") String=B for (Dependency dependency : withDependencies.getDependencies()) { Binding b = injector.getBinding(dependency.getKey()); if(b instanceof InstanceBinding) { if(instanceBinding != null) { fail("Already have an instance binding of: " + instanceBinding + ", and now want to add: " + b); } else { instanceBinding = (InstanceBinding)b; } } else if(b instanceof LinkedKeyBinding) { if(linkedBinding != null) { fail("Already have a linked binding of: " + linkedBinding + ", and now want to add: " + b); } else { linkedBinding = (LinkedKeyBinding)b; } } else { fail("Unexpected dependency of: " + dependency); } } assertNotNull(instanceBinding); assertNotNull(linkedBinding); assertEquals("A", instanceBinding.getInstance()); assertEquals(Key.get(String.class, Names.named("b")), linkedBinding.getLinkedKey()); } /** * Our implementation maintains order, but doesn't guarantee it in the API spec. * TODO: specify the iteration order? */ public void testBindOrderEqualsIterationOrder() { Injector injector = Guice.createInjector( new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("leonardo"); multibinder.addBinding().toInstance("donatello"); install(new AbstractModule() { protected void configure() { Multibinder.newSetBinder(binder(), String.class) .addBinding().toInstance("michaelangelo"); } }); } }, new AbstractModule() { protected void configure() { Multibinder.newSetBinder(binder(), String.class).addBinding().toInstance("raphael"); } }); List inOrder = ImmutableList.copyOf(injector.getInstance(Key.get(setOfString))); assertEquals(ImmutableList.of("leonardo", "donatello", "michaelangelo", "raphael"), inOrder); } @Retention(RUNTIME) @BindingAnnotation @interface Abc {} @Retention(RUNTIME) @BindingAnnotation @interface De {} private Set setOf(T... elements) { Set result = Sets.newHashSet(); result.addAll(Arrays.asList(elements)); return result; } /** * With overrides, we should get the union of all multibindings. */ public void testModuleOverrideAndMultibindings() { Module ab = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("A"); multibinder.addBinding().toInstance("B"); } }; Module cd = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("C"); multibinder.addBinding().toInstance("D"); } }; Module ef = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("E"); multibinder.addBinding().toInstance("F"); } }; Module abcd = Modules.override(ab).with(cd); Injector injector = Guice.createInjector(abcd, ef); assertEquals(ImmutableSet.of("A", "B", "C", "D", "E", "F"), injector.getInstance(Key.get(setOfString))); assertSetVisitor(Key.get(setOfString), stringType, setOf(abcd, ef), BOTH, false, 0, instance("A"), instance("B"), instance("C"), instance("D"), instance("E"), instance("F")); } /** * With overrides, we should get the union of all multibindings. */ public void testModuleOverrideAndMultibindingsWithPermitDuplicates() { Module abc = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("A"); multibinder.addBinding().toInstance("B"); multibinder.addBinding().toInstance("C"); multibinder.permitDuplicates(); } }; Module cd = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("C"); multibinder.addBinding().toInstance("D"); multibinder.permitDuplicates(); } }; Module ef = new AbstractModule() { protected void configure() { Multibinder multibinder = Multibinder.newSetBinder(binder(), String.class); multibinder.addBinding().toInstance("E"); multibinder.addBinding().toInstance("F"); multibinder.permitDuplicates(); } }; Module abcd = Modules.override(abc).with(cd); Injector injector = Guice.createInjector(abcd, ef); assertEquals(ImmutableSet.of("A", "B", "C", "D", "E", "F"), injector.getInstance(Key.get(setOfString))); assertSetVisitor(Key.get(setOfString), stringType, setOf(abcd, ef), BOTH, true, 0, instance("A"), instance("B"), instance("C"), instance("C"), instance("D"), instance("E"), instance("F")); } @BindingAnnotation @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) private static @interface Marker {} @Marker public void testMultibinderMatching() throws Exception { Method m = MultibinderTest.class.getDeclaredMethod("testMultibinderMatching"); assertNotNull(m); final Annotation marker = m.getAnnotation(Marker.class); Injector injector = Guice.createInjector(new AbstractModule() { @Override public void configure() { Multibinder mb1 = Multibinder.newSetBinder(binder(), Integer.class, Marker.class); Multibinder mb2 = Multibinder.newSetBinder(binder(), Integer.class, marker); mb1.addBinding().toInstance(1); mb2.addBinding().toInstance(2); // This assures us that the two binders are equivalent, so we expect the instance added to // each to have been added to one set. assertEquals(mb1, mb2); } }); TypeLiteral> t = new TypeLiteral>() {}; Set s1 = injector.getInstance(Key.get(t, Marker.class)); Set s2 = injector.getInstance(Key.get(t, marker)); // This assures us that the two sets are in fact equal. They may not be same set (as in Java // object identical), but we shouldn't expect that, since probably Guice creates the set each // time in case the elements are dependent on scope. assertEquals(s1, s2); // This ensures that MultiBinder is internally using the correct set name -- // making sure that instances of marker annotations have the same set name as // MarkerAnnotation.class. Set expected = new HashSet(); expected.add(1); expected.add(2); assertEquals(expected, s1); } } guice-3.0/extensions/multibindings/test/com/google/inject/multibindings/AllTests.java0000644000175000017500000000171311214265006031145 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import junit.framework.Test; import junit.framework.TestSuite; /** * @author jessewilson@google.com (Jesse Wilson) */ public class AllTests { public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(MapBinderTest.class); suite.addTestSuite(MultibinderTest.class); return suite; } } guice-3.0/extensions/multibindings/src/0000755000175000017500000000000011214265006020177 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/src/com/0000755000175000017500000000000011214265006020755 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/src/com/google/0000755000175000017500000000000011214265006022231 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/src/com/google/inject/0000755000175000017500000000000011214265006023505 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/src/com/google/inject/multibindings/0000755000175000017500000000000011445101174026356 5ustar drazzibdrazzibguice-3.0/extensions/multibindings/src/com/google/inject/multibindings/MapBinderBinding.java0000644000175000017500000001027611463267514032376 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import java.util.List; import java.util.Map; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; /** * A binding for a MapBinder. *

* Although MapBinders may be injected through a variety of generic types (Map<K, V>, Map * <K, Provider<V>>, Map<K, Set<V>>, Map>, and even Set<Map.Entry<K, Provider<V>>), a * MapBinderBinding exists only on the Binding associated with the Map<K, V> key. Other * bindings can be validated to be derived from this MapBinderBinding using * {@link #containsElement(Element)}. * * @param The fully qualified type of the map, including Map. For example: * MapBinderBinding<Map<String, Snack>> * * @since 3.0 * @author sameb@google.com (Sam Berlin) */ public interface MapBinderBinding { /** Returns the {@link Key} for the map. */ Key getMapKey(); /** * Returns the TypeLiteral describing the keys of the map. *

* The TypeLiteral will always match the type Map's generic type. For example, if getMapKey * returns a key of Map<String, Snack>, then this will always return a * TypeLiteral<String>. */ TypeLiteral getKeyTypeLiteral(); /** * Returns the TypeLiteral describing the values of the map. *

* The TypeLiteral will always match the type Map's generic type. For example, if getMapKey * returns a key of Map<String, Snack>, then this will always return a * TypeLiteral<Snack>. */ TypeLiteral getValueTypeLiteral(); /** * Returns all entries in the Map. The returned list of Map.Entries contains the key and a binding * to the value. Duplicate keys or values will exist as separate Map.Entries in the returned list. * This is only supported on bindings returned from an injector. This will throw * {@link UnsupportedOperationException} if it is called on an element retrieved from * {@link Elements#getElements}. *

* The elements will always match the type Map's generic type. For example, if getMapKey returns a * key of Map<String, Snack>, then this will always return a list of type * List<Map.Entry<String, Binding<Snack>>>. */ List>> getEntries(); /** * Returns true if the MapBinder permits duplicates. This is only supported on bindings returned * from an injector. This will throw {@link UnsupportedOperationException} if it is called on a * MapBinderBinding retrieved from {@link Elements#getElements}. */ boolean permitsDuplicates(); /** * Returns true if this MapBinder contains the given Element in order to build the map or uses the * given Element in order to support building and injecting the map. This will work for * MapBinderBindings retrieved from an injector and {@link Elements#getElements}. Usually this is * only necessary if you are working with elements retrieved from modules (without an Injector), * otherwise {@link #getEntries} and {@link #permitsDuplicates} are better options. *

* If you need to introspect the details of the map, such as the keys, values or if it permits * duplicates, it is necessary to pass the elements through an Injector and use * {@link #getEntries()} and {@link #permitsDuplicates()}. */ boolean containsElement(Element element); } guice-3.0/extensions/multibindings/src/com/google/inject/multibindings/package-info.java0000644000175000017500000000140111461123424031541 0ustar drazzibdrazzib/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Extension for binding multiple instances in a collection; this extension requires {@code * guice-multibindings-3.0.jar}. */ package com.google.inject.multibindings;guice-3.0/extensions/multibindings/src/com/google/inject/multibindings/RealElement.java0000644000175000017500000000334011214265010031410 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import java.lang.annotation.Annotation; import java.util.concurrent.atomic.AtomicInteger; /** * @author jessewilson@google.com (Jesse Wilson) */ class RealElement implements Element { private static final AtomicInteger nextUniqueId = new AtomicInteger(1); private final int uniqueId; private final String setName; RealElement(String setName) { uniqueId = nextUniqueId.getAndIncrement(); this.setName = setName; } public String setName() { return setName; } public int uniqueId() { return uniqueId; } public Class annotationType() { return Element.class; } @Override public String toString() { return "@" + Element.class.getName() + "(setName=" + setName + ",uniqueId=" + uniqueId + ")"; } @Override public boolean equals(Object o) { return o instanceof Element && ((Element) o).setName().equals(setName()) && ((Element) o).uniqueId() == uniqueId(); } @Override public int hashCode() { return 127 * ("setName".hashCode() ^ setName.hashCode()) + 127 * ("uniqueId".hashCode() ^ uniqueId); } } guice-3.0/extensions/multibindings/src/com/google/inject/multibindings/MultibinderBinding.java0000644000175000017500000000631411463267532033011 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import java.util.List; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; /** * A binding for a Multibinder. * * @param The fully qualified type of the set, including Set. For example: * MultibinderBinding<Set<Boolean>> * * @since 3.0 * @author sameb@google.com (Sam Berlin) */ public interface MultibinderBinding { /** Returns the key for the set. */ Key getSetKey(); /** * Returns the TypeLiteral that describes the type of elements in the set. *

* The elements will always match the type Set's generic type. For example, if getSetKey returns a * key of Set<String>, then this will always return a * TypeLiteral<String>. */ TypeLiteral getElementTypeLiteral(); /** * Returns all bindings that make up the set. This is only supported on bindings returned from an * injector. This will throw {@link UnsupportedOperationException} if it is called on an element * retrieved from {@link Elements#getElements}. *

* The elements will always match the type Set's generic type. For example, if getSetKey returns a * key of Set<String>, then this will always return a list of type * List<Binding<String>>. */ List> getElements(); /** * Returns true if the multibinder permits duplicates. This is only supported on bindings returned * from an injector. This will throw {@link UnsupportedOperationException} if it is called on a * MultibinderBinding retrieved from {@link Elements#getElements}. */ boolean permitsDuplicates(); /** * Returns true if this Multibinder uses the given Element. This will be true for bindings that * derive the elements of the set and other bindings that Multibinder uses internally. This will * work for MultibinderBindings retrieved from an injector and {@link Elements#getElements}. * Usually this is only necessary if you are working with elements retrieved from modules (without * an Injector), otherwise {@link #getElements} and {@link #permitsDuplicates} are better options. *

* If you need to introspect the details of the set, such as the values or if it permits * duplicates, it is necessary to pass the elements through an Injector and use * {@link #getElements()} and {@link #permitsDuplicates()}. */ boolean containsElement(Element element); } guice-3.0/extensions/multibindings/src/com/google/inject/multibindings/Element.java0000644000175000017500000000217111214265010030605 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import com.google.inject.BindingAnnotation; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * An internal binding annotation applied to each element in a multibinding. * All elements are assigned a globally-unique id to allow different modules * to contribute multibindings independently. * * @author jessewilson@google.com (Jesse Wilson) */ @Retention(RUNTIME) @BindingAnnotation @interface Element { String setName(); int uniqueId(); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootguice-3.0/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsTargetVisitor.javaguice-3.0/extensions/multibindings/src/com/google/inject/multibindings/MultibindingsTargetVisitor.ja0000644000175000017500000000253611463267540034251 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import com.google.inject.spi.BindingTargetVisitor; /** * A visitor for the multibinder extension. *

* If your {@link BindingTargetVisitor} implements this interface, bindings created by using * {@link Multibinder} or {@link MapBinder} will be visited through this interface. * * @since 3.0 * @author sameb@google.com (Sam Berlin) */ public interface MultibindingsTargetVisitor extends BindingTargetVisitor { /** * Visits a binding created through {@link Multibinder}. */ V visit(MultibinderBinding multibinding); /** * Visits a binding created through {@link MapBinder}. */ V visit(MapBinderBinding mapbinding); } guice-3.0/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java0000644000175000017500000006400411463267730031101 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import com.google.inject.Binder; import com.google.inject.Binding; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.binder.LinkedBindingBuilder; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import com.google.inject.multibindings.Multibinder.RealMultibinder; import static com.google.inject.multibindings.Multibinder.checkConfiguration; import static com.google.inject.multibindings.Multibinder.checkNotNull; import static com.google.inject.multibindings.Multibinder.setOf; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderLookup; import com.google.inject.spi.ProviderWithDependencies; import com.google.inject.spi.ProviderWithExtensionVisitor; import com.google.inject.spi.Toolable; import com.google.inject.util.Types; import static com.google.inject.util.Types.newParameterizedTypeWithOwner; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /** * An API to bind multiple map entries separately, only to later inject them as * a complete map. MapBinder is intended for use in your application's module: *


 * public class SnacksModule extends AbstractModule {
 *   protected void configure() {
 *     MapBinder<String, Snack> mapbinder
 *         = MapBinder.newMapBinder(binder(), String.class, Snack.class);
 *     mapbinder.addBinding("twix").toInstance(new Twix());
 *     mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
 *     mapbinder.addBinding("skittles").to(Skittles.class);
 *   }
 * }
* *

With this binding, a {@link Map}{@code } can now be * injected: *


 * class SnackMachine {
 *   {@literal @}Inject
 *   public SnackMachine(Map<String, Snack> snacks) { ... }
 * }
* *

In addition to binding {@code Map}, a mapbinder will also bind * {@code Map>} for lazy value provision: *


 * class SnackMachine {
 *   {@literal @}Inject
 *   public SnackMachine(Map<String, Provider<Snack>> snackProviders) { ... }
 * }
* *

Contributing mapbindings from different modules is supported. For example, * it is okay to have both {@code CandyModule} and {@code ChipsModule} both * create their own {@code MapBinder}, and to each contribute * bindings to the snacks map. When that map is injected, it will contain * entries from both modules. * *

The map's iteration order is consistent with the binding order. This is * convenient when multiple elements are contributed by the same module because * that module can order its bindings appropriately. Avoid relying on the * iteration order of elements contributed by different modules, since there is * no equivalent mechanism to order modules. * *

The map is unmodifiable. Elements can only be added to the map by * configuring the MapBinder. Elements can never be removed from the map. * *

Values are resolved at map injection time. If a value is bound to a * provider, that provider's get method will be called each time the map is * injected (unless the binding is also scoped, or a map of providers is injected). * *

Annotations are used to create different maps of the same key/value * type. Each distinct annotation gets its own independent map. * *

Keys must be distinct. If the same key is bound more than * once, map injection will fail. However, use {@link #permitDuplicates()} in * order to allow duplicate keys; extra bindings to {@code Map>} and * {@code Map>} will be added. * *

Keys must be non-null. {@code addBinding(null)} will * throw an unchecked exception. * *

Values must be non-null to use map injection. If any * value is null, map injection will fail (although injecting a map of providers * will not). * * @author dpb@google.com (David P. Baker) */ public abstract class MapBinder { private MapBinder() {} /** * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a * {@link Map} that is itself bound with no binding annotation. */ public static MapBinder newMapBinder(Binder binder, TypeLiteral keyType, TypeLiteral valueType) { binder = binder.skipSources(MapBinder.class, RealMapBinder.class); return newMapBinder(binder, keyType, valueType, Key.get(mapOf(keyType, valueType)), Key.get(mapOfProviderOf(keyType, valueType)), Key.get(mapOf(keyType, setOf(valueType))), Key.get(mapOfSetOfProviderOf(keyType, valueType)), Multibinder.newSetBinder(binder, entryOfProviderOf(keyType, valueType))); } /** * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a * {@link Map} that is itself bound with no binding annotation. */ public static MapBinder newMapBinder(Binder binder, Class keyType, Class valueType) { return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType)); } /** * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a * {@link Map} that is itself bound with {@code annotation}. */ public static MapBinder newMapBinder(Binder binder, TypeLiteral keyType, TypeLiteral valueType, Annotation annotation) { binder = binder.skipSources(MapBinder.class, RealMapBinder.class); return newMapBinder(binder, keyType, valueType, Key.get(mapOf(keyType, valueType), annotation), Key.get(mapOfProviderOf(keyType, valueType), annotation), Key.get(mapOf(keyType, setOf(valueType)), annotation), Key.get(mapOfSetOfProviderOf(keyType, valueType), annotation), Multibinder.newSetBinder(binder, entryOfProviderOf(keyType, valueType), annotation)); } /** * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a * {@link Map} that is itself bound with {@code annotation}. */ public static MapBinder newMapBinder(Binder binder, Class keyType, Class valueType, Annotation annotation) { return newMapBinder(binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType), annotation); } /** * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a * {@link Map} that is itself bound with {@code annotationType}. */ public static MapBinder newMapBinder(Binder binder, TypeLiteral keyType, TypeLiteral valueType, Class annotationType) { binder = binder.skipSources(MapBinder.class, RealMapBinder.class); return newMapBinder(binder, keyType, valueType, Key.get(mapOf(keyType, valueType), annotationType), Key.get(mapOfProviderOf(keyType, valueType), annotationType), Key.get(mapOf(keyType, setOf(valueType)), annotationType), Key.get(mapOfSetOfProviderOf(keyType, valueType), annotationType), Multibinder.newSetBinder(binder, entryOfProviderOf(keyType, valueType), annotationType)); } /** * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a * {@link Map} that is itself bound with {@code annotationType}. */ public static MapBinder newMapBinder(Binder binder, Class keyType, Class valueType, Class annotationType) { return newMapBinder( binder, TypeLiteral.get(keyType), TypeLiteral.get(valueType), annotationType); } @SuppressWarnings("unchecked") // a map of is safely a Map static TypeLiteral> mapOf( TypeLiteral keyType, TypeLiteral valueType) { return (TypeLiteral>) TypeLiteral.get( Types.mapOf(keyType.getType(), valueType.getType())); } @SuppressWarnings("unchecked") // a provider map is safely a Map> static TypeLiteral>> mapOfProviderOf( TypeLiteral keyType, TypeLiteral valueType) { return (TypeLiteral>>) TypeLiteral.get( Types.mapOf(keyType.getType(), Types.providerOf(valueType.getType()))); } @SuppressWarnings("unchecked") // a provider map > is safely a Map>> static TypeLiteral>>> mapOfSetOfProviderOf( TypeLiteral keyType, TypeLiteral valueType) { return (TypeLiteral>>>) TypeLiteral.get( Types.mapOf(keyType.getType(), Types.setOf(Types.providerOf(valueType.getType())))); } @SuppressWarnings("unchecked") // a provider entry is safely a Map.Entry> static TypeLiteral>> entryOfProviderOf( TypeLiteral keyType, TypeLiteral valueType) { return (TypeLiteral>>) TypeLiteral.get(newParameterizedTypeWithOwner( Map.class, Entry.class, keyType.getType(), Types.providerOf(valueType.getType()))); } private static MapBinder newMapBinder(Binder binder, TypeLiteral keyType, TypeLiteral valueType, Key> mapKey, Key>> providerMapKey, Key>> multimapKey, Key>>> providerMultimapKey, Multibinder>> entrySetBinder) { RealMapBinder mapBinder = new RealMapBinder( binder, keyType, valueType, mapKey, providerMapKey, multimapKey, providerMultimapKey, entrySetBinder); binder.install(mapBinder); return mapBinder; } /** * Configures the {@code MapBinder} to handle duplicate entries. *

When multiple equal keys are bound, the value that gets included in the map is * arbitrary. *

In addition to the {@code Map} and {@code Map>} * maps that are normally bound, a {@code Map>} and * {@code Map>>} are also bound, which contain * all values bound to each key. *

* When multiple modules contribute elements to the map, this configuration * option impacts all of them. * * @return this map binder * @since 3.0 */ public abstract MapBinder permitDuplicates(); /** * Returns a binding builder used to add a new entry in the map. Each * key must be distinct (and non-null). Bound providers will be evaluated each * time the map is injected. * *

It is an error to call this method without also calling one of the * {@code to} methods on the returned binding builder. * *

Scoping elements independently is supported. Use the {@code in} method * to specify a binding scope. */ public abstract LinkedBindingBuilder addBinding(K key); /** * The actual mapbinder plays several roles: * *

As a MapBinder, it acts as a factory for LinkedBindingBuilders for * each of the map's values. It delegates to a {@link Multibinder} of * entries (keys to value providers). * *

As a Module, it installs the binding to the map itself, as well as to * a corresponding map whose values are providers. It uses the entry set * multibinder to construct the map and the provider map. * *

As a module, this implements equals() and hashcode() in order to trick * Guice into executing its configure() method only once. That makes it so * that multiple mapbinders can be created for the same target map, but * only one is bound. Since the list of bindings is retrieved from the * injector itself (and not the mapbinder), each mapbinder has access to * all contributions from all equivalent mapbinders. * *

Rather than binding a single Map.Entry<K, V>, the map binder * binds keys and values independently. This allows the values to be properly * scoped. * *

We use a subclass to hide 'implements Module' from the public API. */ private static final class RealMapBinder extends MapBinder implements Module { private final TypeLiteral keyType; private final TypeLiteral valueType; private final Key> mapKey; private final Key>> providerMapKey; private final Key>> multimapKey; private final Key>>> providerMultimapKey; private final RealMultibinder>> entrySetBinder; /* the target injector's binder. non-null until initialization, null afterwards */ private Binder binder; private boolean permitDuplicates; private ImmutableList>> mapBindings; private RealMapBinder(Binder binder, TypeLiteral keyType, TypeLiteral valueType, Key> mapKey, Key>> providerMapKey, Key>> multimapKey, Key>>> providerMultimapKey, Multibinder>> entrySetBinder) { this.keyType = keyType; this.valueType = valueType; this.mapKey = mapKey; this.providerMapKey = providerMapKey; this.multimapKey = multimapKey; this.providerMultimapKey = providerMultimapKey; this.entrySetBinder = (RealMultibinder>>) entrySetBinder; this.binder = binder; } @Override public MapBinder permitDuplicates() { entrySetBinder.permitDuplicates(); binder.install(new MultimapBinder( multimapKey, providerMultimapKey, entrySetBinder.getSetKey())); return this; } /** * This creates two bindings. One for the {@code Map.Entry>} * and another for {@code V}. */ @Override public LinkedBindingBuilder addBinding(K key) { checkNotNull(key, "key"); checkConfiguration(!isInitialized(), "MapBinder was already initialized"); Key valueKey = Key.get(valueType, new RealElement(entrySetBinder.getSetName())); entrySetBinder.addBinding().toInstance(new MapEntry>(key, binder.getProvider(valueKey), valueKey)); return binder.bind(valueKey); } public void configure(Binder binder) { checkConfiguration(!isInitialized(), "MapBinder was already initialized"); final ImmutableSet> dependencies = ImmutableSet.>of(Dependency.get(entrySetBinder.getSetKey())); // Binds a Map> from a collection of Set>. final Provider>>> entrySetProvider = binder .getProvider(entrySetBinder.getSetKey()); binder.bind(providerMapKey).toProvider(new RealMapBinderProviderWithDependencies>>(mapKey) { private Map> providerMap; @SuppressWarnings({ "unused", "unchecked" }) @Toolable @Inject void initialize(Injector injector) { RealMapBinder.this.binder = null; permitDuplicates = entrySetBinder.permitsDuplicates(injector); Map> providerMapMutable = new LinkedHashMap>(); List>> bindingsMutable = Lists.newArrayList(); for (Entry> entry : entrySetProvider.get()) { Provider previous = providerMapMutable.put(entry.getKey(), entry.getValue()); checkConfiguration(previous == null || permitDuplicates, "Map injection failed due to duplicated key \"%s\"", entry.getKey()); Key valueKey = (Key)((MapEntry)entry).getValueKey(); bindingsMutable.add(new MapEntry(entry.getKey(), injector.getBinding(valueKey), valueKey)); } providerMap = ImmutableMap.copyOf(providerMapMutable); mapBindings = ImmutableList.copyOf(bindingsMutable); } public Map> get() { return providerMap; } public Set> getDependencies() { return dependencies; } }); final Provider>> mapProvider = binder.getProvider(providerMapKey); binder.bind(mapKey).toProvider(new RealMapWithExtensionProvider>(mapKey) { public Map get() { Map map = new LinkedHashMap(); for (Entry> entry : mapProvider.get().entrySet()) { V value = entry.getValue().get(); K key = entry.getKey(); checkConfiguration(value != null, "Map injection failed due to null value for key \"%s\"", key); map.put(key, value); } return Collections.unmodifiableMap(map); } public Set> getDependencies() { return dependencies; } @SuppressWarnings("unchecked") public R acceptExtensionVisitor(BindingTargetVisitor visitor, ProviderInstanceBinding binding) { if (visitor instanceof MultibindingsTargetVisitor) { return ((MultibindingsTargetVisitor, R>)visitor).visit(this); } else { return visitor.visit(binding); } } public Key> getMapKey() { return mapKey; } public TypeLiteral getKeyTypeLiteral() { return keyType; } public TypeLiteral getValueTypeLiteral() { return valueType; } @SuppressWarnings("unchecked") public List>> getEntries() { if (isInitialized()) { return (List)mapBindings; // safe because mapBindings is immutable } else { throw new UnsupportedOperationException("getElements() not supported for module bindings"); } } public boolean permitsDuplicates() { if (isInitialized()) { return permitDuplicates; } else { throw new UnsupportedOperationException("permitsDuplicates() not supported for module bindings"); } } public boolean containsElement(com.google.inject.spi.Element element) { if (entrySetBinder.containsElement(element)) { return true; } else { Key key; if (element instanceof Binding) { key = ((Binding)element).getKey(); } else if (element instanceof ProviderLookup) { key = ((ProviderLookup)element).getKey(); } else { return false; // cannot match; } return key.equals(mapKey) || key.equals(providerMapKey) || key.equals(multimapKey) || key.equals(providerMultimapKey) || key.equals(entrySetBinder.getSetKey()) || matchesValueKey(key); } } }); } /** Returns true if the key indicates this is a value in the map. */ private boolean matchesValueKey(Key key) { return key.getAnnotation() instanceof Element && ((Element) key.getAnnotation()).setName().equals(entrySetBinder.getSetName()) && key.getTypeLiteral().equals(valueType); } private boolean isInitialized() { return binder == null; } @Override public boolean equals(Object o) { return o instanceof RealMapBinder && ((RealMapBinder) o).mapKey.equals(mapKey); } @Override public int hashCode() { return mapKey.hashCode(); } /** * Binds {@code Map>} and {{@code Map>>}. */ private static final class MultimapBinder implements Module { private final Key>> multimapKey; private final Key>>> providerMultimapKey; private final Key>>> entrySetKey; public MultimapBinder( Key>> multimapKey, Key>>> providerMultimapKey, Key>>> entrySetKey) { this.multimapKey = multimapKey; this.providerMultimapKey = providerMultimapKey; this.entrySetKey = entrySetKey; } public void configure(Binder binder) { final ImmutableSet> dependencies = ImmutableSet.>of(Dependency.get(entrySetKey)); final Provider>>> entrySetProvider = binder.getProvider(entrySetKey); // Binds a Map>> from a collection of Map> if // permitDuplicates was called. binder.bind(providerMultimapKey).toProvider( new RealMapBinderProviderWithDependencies>>>(multimapKey) { private Map>> providerMultimap; @SuppressWarnings("unused") @Inject void initialize(Injector injector) { Map>> providerMultimapMutable = new LinkedHashMap>>(); for (Entry> entry : entrySetProvider.get()) { if (!providerMultimapMutable.containsKey(entry.getKey())) { providerMultimapMutable.put( entry.getKey(), ImmutableSet.>builder()); } providerMultimapMutable.get(entry.getKey()).add(entry.getValue()); } ImmutableMap.Builder>> providerMultimapBuilder = ImmutableMap.builder(); for (Entry>> entry : providerMultimapMutable.entrySet()) { providerMultimapBuilder.put(entry.getKey(), entry.getValue().build()); } providerMultimap = providerMultimapBuilder.build(); } public Map>> get() { return providerMultimap; } public Set> getDependencies() { return dependencies; } }); final Provider>>> multimapProvider = binder.getProvider(providerMultimapKey); binder.bind(multimapKey).toProvider(new RealMapBinderProviderWithDependencies>>(multimapKey) { public Map> get() { ImmutableMap.Builder> multimapBuilder = ImmutableMap.builder(); for (Entry>> entry : multimapProvider.get().entrySet()) { K key = entry.getKey(); ImmutableSet.Builder valuesBuilder = ImmutableSet.builder(); for (Provider valueProvider : entry.getValue()) { V value = valueProvider.get(); checkConfiguration(value != null, "Multimap injection failed due to null value for key \"%s\"", key); valuesBuilder.add(value); } multimapBuilder.put(key, valuesBuilder.build()); } return multimapBuilder.build(); } public Set> getDependencies() { return dependencies; } }); } } private static final class MapEntry implements Map.Entry { private final K key; private final V value; private final Key valueKey; private MapEntry(K key, V value, Key valueKey) { this.key = key; this.value = value; this.valueKey = valueKey; } public Key getValueKey() { return valueKey; } public K getKey() { return key; } public V getValue() { return value; } public V setValue(V value) { throw new UnsupportedOperationException(); } @Override public boolean equals(Object obj) { return obj instanceof Map.Entry && key.equals(((Map.Entry) obj).getKey()) && value.equals(((Map.Entry) obj).getValue()); } @Override public int hashCode() { return 127 * ("key".hashCode() ^ key.hashCode()) + 127 * ("value".hashCode() ^ value.hashCode()); } @Override public String toString() { return "MapEntry(" + key + ", " + value + ")"; } } private static abstract class RealMapWithExtensionProvider extends RealMapBinderProviderWithDependencies implements ProviderWithExtensionVisitor, MapBinderBinding { public RealMapWithExtensionProvider(Object equality) { super(equality); } } /** * A base class for ProviderWithDependencies that need equality * based on a specific object. */ private static abstract class RealMapBinderProviderWithDependencies implements ProviderWithDependencies { private final Object equality; public RealMapBinderProviderWithDependencies(Object equality) { this.equality = equality; } @Override public boolean equals(Object obj) { return this.getClass() == obj.getClass() && equality.equals(((RealMapBinderProviderWithDependencies)obj).equality); } } } } guice-3.0/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java0000644000175000017500000004110411463267740031513 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.multibindings; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Binding; import com.google.inject.ConfigurationException; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.TypeLiteral; import com.google.inject.binder.LinkedBindingBuilder; import com.google.inject.internal.Annotations; import com.google.inject.internal.Errors; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import static com.google.inject.name.Names.named; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.Message; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import com.google.inject.spi.Toolable; import com.google.inject.util.Types; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; /** * An API to bind multiple values separately, only to later inject them as a * complete collection. Multibinder is intended for use in your application's * module: *


 * public class SnacksModule extends AbstractModule {
 *   protected void configure() {
 *     Multibinder<Snack> multibinder
 *         = Multibinder.newSetBinder(binder(), Snack.class);
 *     multibinder.addBinding().toInstance(new Twix());
 *     multibinder.addBinding().toProvider(SnickersProvider.class);
 *     multibinder.addBinding().to(Skittles.class);
 *   }
 * }
* *

With this binding, a {@link Set}{@code } can now be injected: *


 * class SnackMachine {
 *   {@literal @}Inject
 *   public SnackMachine(Set<Snack> snacks) { ... }
 * }
* *

Contributing multibindings from different modules is supported. For * example, it is okay to have both {@code CandyModule} and {@code ChipsModule} * to both create their own {@code Multibinder}, and to each contribute * bindings to the set of snacks. When that set is injected, it will contain * elements from both modules. * *

The set's iteration order is consistent with the binding order. This is * convenient when multiple elements are contributed by the same module because * that module can order its bindings appropriately. Avoid relying on the * iteration order of elements contributed by different modules, since there is * no equivalent mechanism to order modules. * *

The set is unmodifiable. Elements can only be added to the set by * configuring the multibinder. Elements can never be removed from the set. * *

Elements are resolved at set injection time. If an element is bound to a * provider, that provider's get method will be called each time the set is * injected (unless the binding is also scoped). * *

Annotations are be used to create different sets of the same element * type. Each distinct annotation gets its own independent collection of * elements. * *

Elements must be distinct. If multiple bound elements * have the same value, set injection will fail. * *

Elements must be non-null. If any set element is null, * set injection will fail. * * @author jessewilson@google.com (Jesse Wilson) */ public abstract class Multibinder { private Multibinder() {} /** * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is * itself bound with no binding annotation. */ public static Multibinder newSetBinder(Binder binder, TypeLiteral type) { binder = binder.skipSources(RealMultibinder.class, Multibinder.class); RealMultibinder result = new RealMultibinder(binder, type, Key.get(Multibinder.setOf(type))); binder.install(result); return result; } /** * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is * itself bound with no binding annotation. */ public static Multibinder newSetBinder(Binder binder, Class type) { return newSetBinder(binder, TypeLiteral.get(type)); } /** * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is * itself bound with {@code annotation}. */ public static Multibinder newSetBinder( Binder binder, TypeLiteral type, Annotation annotation) { binder = binder.skipSources(RealMultibinder.class, Multibinder.class); RealMultibinder result = new RealMultibinder(binder, type, Key.get(Multibinder.setOf(type), annotation)); binder.install(result); return result; } /** * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is * itself bound with {@code annotation}. */ public static Multibinder newSetBinder( Binder binder, Class type, Annotation annotation) { return newSetBinder(binder, TypeLiteral.get(type), annotation); } /** * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is * itself bound with {@code annotationType}. */ public static Multibinder newSetBinder(Binder binder, TypeLiteral type, Class annotationType) { binder = binder.skipSources(RealMultibinder.class, Multibinder.class); RealMultibinder result = new RealMultibinder(binder, type, Key.get(Multibinder.setOf(type), annotationType)); binder.install(result); return result; } /** * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is * itself bound with {@code annotationType}. */ public static Multibinder newSetBinder(Binder binder, Class type, Class annotationType) { return newSetBinder(binder, TypeLiteral.get(type), annotationType); } @SuppressWarnings("unchecked") // wrapping a T in a Set safely returns a Set static TypeLiteral> setOf(TypeLiteral elementType) { Type type = Types.setOf(elementType.getType()); return (TypeLiteral>) TypeLiteral.get(type); } /** * Configures the bound set to silently discard duplicate elements. When multiple equal values are * bound, the one that gets included is arbitrary. When multiple modules contribute elements to * the set, this configuration option impacts all of them. * * @return this multibinder * @since 3.0 */ public abstract Multibinder permitDuplicates(); /** * Returns a binding builder used to add a new element in the set. Each * bound element must have a distinct value. Bound providers will be * evaluated each time the set is injected. * *

It is an error to call this method without also calling one of the * {@code to} methods on the returned binding builder. * *

Scoping elements independently is supported. Use the {@code in} method * to specify a binding scope. */ public abstract LinkedBindingBuilder addBinding(); /** * The actual multibinder plays several roles: * *

As a Multibinder, it acts as a factory for LinkedBindingBuilders for * each of the set's elements. Each binding is given an annotation that * identifies it as a part of this set. * *

As a Module, it installs the binding to the set itself. As a module, * this implements equals() and hashcode() in order to trick Guice into * executing its configure() method only once. That makes it so that * multiple multibinders can be created for the same target collection, but * only one is bound. Since the list of bindings is retrieved from the * injector itself (and not the multibinder), each multibinder has access to * all contributions from all multibinders. * *

As a Provider, this constructs the set instances. * *

We use a subclass to hide 'implements Module, Provider' from the public * API. */ static final class RealMultibinder extends Multibinder implements Module, ProviderWithExtensionVisitor>, HasDependencies, MultibinderBinding> { private final TypeLiteral elementType; private final String setName; private final Key> setKey; private final Key permitDuplicatesKey; /* the target injector's binder. non-null until initialization, null afterwards */ private Binder binder; /* a binding for each element in the set. null until initialization, non-null afterwards */ private ImmutableList> bindings; private Set> dependencies; /** whether duplicates are allowed. Possibly configured by a different instance */ private boolean permitDuplicates; private RealMultibinder(Binder binder, TypeLiteral elementType, Key> setKey) { this.binder = checkNotNull(binder, "binder"); this.elementType = checkNotNull(elementType, "elementType"); this.setKey = checkNotNull(setKey, "setKey"); this.setName = nameOf(setKey); this.permitDuplicatesKey = Key.get(Boolean.class, named(toString() + " permits duplicates")); } /** * Returns the name the set should use. This is based on the annotation. * If the annotation has an instance and is not a marker annotation, * we ask the annotation for its toString. If it was a marker annotation * or just an annotation type, we use the annotation's name. Otherwise, * the name is the empty string. */ private String nameOf(Key key) { Annotation annotation = setKey.getAnnotation(); Class annotationType = setKey.getAnnotationType(); if (annotation != null && !Annotations.isMarker(annotationType)) { return setKey.getAnnotation().toString(); } else if(setKey.getAnnotationType() != null) { return "@" + setKey.getAnnotationType().getName(); } else { return ""; } } @SuppressWarnings("unchecked") public void configure(Binder binder) { checkConfiguration(!isInitialized(), "Multibinder was already initialized"); binder.bind(setKey).toProvider(this); } @Override public Multibinder permitDuplicates() { binder.install(new PermitDuplicatesModule(permitDuplicatesKey)); return this; } @Override public LinkedBindingBuilder addBinding() { checkConfiguration(!isInitialized(), "Multibinder was already initialized"); return binder.bind(Key.get(elementType, new RealElement(setName))); } /** * Invoked by Guice at Injector-creation time to prepare providers for each * element in this set. At this time the set's size is known, but its * contents are only evaluated when get() is invoked. */ @Toolable @Inject void initialize(Injector injector) { List> bindings = Lists.newArrayList(); List> dependencies = Lists.newArrayList(); for (Binding entry : injector.findBindingsByType(elementType)) { if (keyMatches(entry.getKey())) { @SuppressWarnings("unchecked") // protected by findBindingsByType() Binding binding = (Binding) entry; bindings.add(binding); dependencies.add(Dependency.get(binding.getKey())); } } this.bindings = ImmutableList.copyOf(bindings); this.dependencies = ImmutableSet.copyOf(dependencies); this.permitDuplicates = permitsDuplicates(injector); this.binder = null; } boolean permitsDuplicates(Injector injector) { return injector.getBindings().containsKey(permitDuplicatesKey); } private boolean keyMatches(Key key) { return key.getTypeLiteral().equals(elementType) && key.getAnnotation() instanceof Element && ((Element) key.getAnnotation()).setName().equals(setName); } private boolean isInitialized() { return binder == null; } public Set get() { checkConfiguration(isInitialized(), "Multibinder is not initialized"); Set result = new LinkedHashSet(); for (Binding binding : bindings) { final T newValue = binding.getProvider().get(); checkConfiguration(newValue != null, "Set injection failed due to null element"); checkConfiguration(result.add(newValue) || permitDuplicates, "Set injection failed due to duplicated element \"%s\"", newValue); } return Collections.unmodifiableSet(result); } @SuppressWarnings("unchecked") public V acceptExtensionVisitor( BindingTargetVisitor visitor, ProviderInstanceBinding binding) { if(visitor instanceof MultibindingsTargetVisitor) { return ((MultibindingsTargetVisitor, V>)visitor).visit(this); } else { return visitor.visit(binding); } } String getSetName() { return setName; } public TypeLiteral getElementTypeLiteral() { return elementType; } public Key> getSetKey() { return setKey; } @SuppressWarnings("unchecked") public List> getElements() { if(isInitialized()) { return (List)bindings; // safe because bindings is immutable. } else { throw new UnsupportedOperationException("getElements() not supported for module bindings"); } } public boolean permitsDuplicates() { if(isInitialized()) { return permitDuplicates; } else { throw new UnsupportedOperationException("permitsDuplicates() not supported for module bindings"); } } public boolean containsElement(com.google.inject.spi.Element element) { if(element instanceof Binding) { Binding binding = (Binding)element; return keyMatches(binding.getKey()) || binding.getKey().equals(permitDuplicatesKey) || binding.getKey().equals(setKey); } else { return false; } } public Set> getDependencies() { if (!isInitialized()) { return ImmutableSet.>of(Dependency.get(Key.get(Injector.class))); } else { return dependencies; } } @Override public boolean equals(Object o) { return o instanceof RealMultibinder && ((RealMultibinder) o).setKey.equals(setKey); } @Override public int hashCode() { return setKey.hashCode(); } @Override public String toString() { return new StringBuilder() .append(setName) .append(setName.length() > 0 ? " " : "") .append("Multibinder<") .append(elementType) .append(">") .toString(); } } /** * We install the permit duplicates configuration as its own binding, all by itself. This way, * if only one of a multibinder's users remember to call permitDuplicates(), they're still * permitted. */ private static class PermitDuplicatesModule extends AbstractModule { private final Key key; PermitDuplicatesModule(Key key) { this.key = key; } @Override protected void configure() { bind(key).toInstance(true); } @Override public boolean equals(Object o) { return o instanceof PermitDuplicatesModule && ((PermitDuplicatesModule) o).key.equals(key); } @Override public int hashCode() { return getClass().hashCode() ^ key.hashCode(); } } static void checkConfiguration(boolean condition, String format, Object... args) { if (condition) { return; } throw new ConfigurationException(ImmutableSet.of(new Message(Errors.format(format, args)))); } static T checkNotNull(T reference, String name) { if (reference != null) { return reference; } NullPointerException npe = new NullPointerException(name); throw new ConfigurationException(ImmutableSet.of( new Message(ImmutableList.of(), npe.toString(), npe))); } } guice-3.0/extensions/multibindings/multibindings.iml0000644000175000017500000000111111214265010022750 0ustar drazzibdrazzib guice-3.0/extensions/throwingproviders/0000755000175000017500000000000011542727754020360 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/build/0000755000175000017500000000000011542727754021457 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/build/META-INF/0000755000175000017500000000000011542727754022617 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/build/META-INF/MANIFEST.MF0000644000175000017500000000123711542727752024252 0ustar drazzibdrazzibManifest-Version: 1.0 Export-Package: com.google.inject.throwingproviders;version="1.3" Bundle-Name: guice-throwingproviders Created-By: 1.6.0_23 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-Copyright: Copyright (C) 2006 Google Inc. Bundle-Vendor: Google, Inc. Fragment-Host: com.google.inject Bundle-Version: 3.0 Bundle-ManifestVersion: 2 Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-Description: Guice is a lightweight dependency injection framew ork for Java 5 and above Bundle-DocURL: http://code.google.com/p/google-guice/ Bundle-SymbolicName: com.google.inject.throwingproviders guice-3.0/extensions/throwingproviders/build/dist/0000755000175000017500000000000011542727754022422 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/build/classes/0000755000175000017500000000000011542727754023114 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/build/classes/com/0000755000175000017500000000000011542727754023672 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/build/classes/com/google/0000755000175000017500000000000011542727754025146 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/build/classes/com/google/inject/0000755000175000017500000000000011542727754026422 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/build/classes/com/google/inject/throwingproviders/0000755000175000017500000000000011542727754032221 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/pom.xml0000644000175000017500000000110411460132762021655 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-throwingproviders Google Guice - Extensions - ThrowingProviders guice-3.0/extensions/throwingproviders/build.xml0000644000175000017500000000125411461503376022173 0ustar drazzibdrazzib guice-3.0/extensions/throwingproviders/build.properties0000644000175000017500000000027711461376774023605 0ustar drazzibdrazziblib.dir=../../lib src.dir=src test.dir=test build.dir=build test.class=com.google.inject.throwingproviders.ThrowingProviderBinderTest module=com.google.inject.throwingproviders fragment=true guice-3.0/extensions/throwingproviders/throwingproviders.iml0000644000175000017500000000145411214265006024645 0ustar drazzibdrazzib guice-3.0/extensions/throwingproviders/test/0000755000175000017500000000000011214265006021316 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/test/com/0000755000175000017500000000000011214265006022074 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/test/com/google/0000755000175000017500000000000011214265006023350 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/test/com/google/inject/0000755000175000017500000000000011214265006024624 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/0000755000175000017500000000000011475262662030441 5ustar drazzibdrazzib././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootguice-3.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderMethodsModuleTest.javaguice-3.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderMetho0000644000175000017500000001354511475262662034432 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.throwingproviders; import com.google.inject.AbstractModule; import com.google.inject.BindingAnnotation; import com.google.inject.Exposed; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.PrivateModule; import com.google.inject.Provides; import com.google.inject.TypeLiteral; import com.google.inject.name.Named; import com.google.inject.name.Names; import junit.framework.TestCase; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.BindException; import java.rmi.RemoteException; /** * Test methods for {@link CheckedProviderMethodsModule}. */ public class CheckedProviderMethodsModuleTest extends TestCase { private final TypeLiteral> rpcProviderOfString = new TypeLiteral>() { }; private final TypeLiteral> rpcProviderOfInteger = new TypeLiteral>() { }; private final TypeLiteral> rpcProviderOfLong = new TypeLiteral>() { }; private final TypeLiteral> rpcProviderOfFloat = new TypeLiteral>() { }; private final TypeLiteral>> rpcProviderOfPair = new TypeLiteral>>() { }; private final TestScope testScope = new TestScope(); interface RpcProvider extends CheckedProvider { T get() throws RemoteException, BindException; } @Retention(RetentionPolicy.RUNTIME) @BindingAnnotation @interface TestAnnotation { } class TestModule extends AbstractModule { private int nextIntToReturn = 100; @Override protected void configure() { bindScope(TestScope.Scoped.class, testScope); install(ThrowingProviderBinder.forModule(this)); install(new TestPrivateModule()); } @CheckedProvides(RpcProvider.class) String getSomeStringFromServer() { return "Works"; } @CheckedProvides(RpcProvider.class) @TestScope.Scoped int getSomeIntegerFromServer() { return nextIntToReturn; } @CheckedProvides(RpcProvider.class) @TestAnnotation long getSomeLongFromServer() { return 0xffL; } @Provides double getSomeDouble() { return 2.0d; } @CheckedProvides(RpcProvider.class) Pair getSomePair(Double input) { return new Pair(input * 2, "foo"); } @CheckedProvides(RpcProvider.class) float getFloat() throws BindException { throw new BindException("foo"); } void setNextIntToReturn(int next) { nextIntToReturn = next; } } class TestPrivateModule extends PrivateModule { @Override protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @CheckedProvides(RpcProvider.class) @Named("fruit") @Exposed String provideApples() { return "apple"; } } public void testNoAnnotationNoScope() throws BindException, RemoteException { Injector injector = Guice.createInjector(new TestModule()); RpcProvider provider = injector .getInstance(Key.get(rpcProviderOfString)); assertEquals("Works", provider.get()); } public void testWithScope() throws BindException, RemoteException { TestModule testModule = new TestModule(); Injector injector = Guice.createInjector(testModule); RpcProvider provider = injector .getInstance(Key.get(rpcProviderOfInteger)); assertEquals((Integer)100, provider.get()); testModule.setNextIntToReturn(120); assertEquals((Integer)100, provider.get()); testScope.beginNewScope(); assertEquals((Integer)120, provider.get()); } public void testWithAnnotation() throws BindException, RemoteException { TestModule testModule = new TestModule(); Injector injector = Guice.createInjector(testModule); RpcProvider provider = injector .getInstance(Key.get(rpcProviderOfLong, TestAnnotation.class)); assertEquals((Long)0xffL, provider.get()); } public void testWithInjectedParameters() throws BindException, RemoteException { TestModule testModule = new TestModule(); Injector injector = Guice.createInjector(testModule); RpcProvider> provider = injector .getInstance(Key.get(rpcProviderOfPair)); Pair pair = provider.get(); assertEquals(pair.first, 4.0d); } public void testWithThrownException() { TestModule testModule = new TestModule(); Injector injector = Guice.createInjector(testModule); RpcProvider provider = injector .getInstance(Key.get(rpcProviderOfFloat)); try { provider.get(); fail(); } catch (RemoteException e) { fail(); } catch (BindException e) { // good } } public void testExposedMethod() throws BindException, RemoteException { TestModule testModule = new TestModule(); Injector injector = Guice.createInjector(testModule); RpcProvider provider = injector .getInstance(Key.get(rpcProviderOfString, Names.named("fruit"))); assertEquals("apple", provider.get()); } private static class Pair { A first; B second; Pair(A a, B b) { this.first= a; this.second = b; } } }guice-3.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/TestScope.java0000644000175000017500000000321711214265006033202 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.throwingproviders; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.ScopeAnnotation; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.util.HashMap; import java.util.Map; /** * A simple scope that can be explicitly reset. * * @author jmourits@google.com (Jerome Mourits) */ class TestScope implements Scope { @Retention(RUNTIME) @ScopeAnnotation public @interface Scoped { } private Map inScopeObjectsMap = new HashMap(); public Provider scope( final Key key, final Provider provider) { return new Provider() { @SuppressWarnings({"unchecked"}) public T get() { T t = (T) inScopeObjectsMap.get(key); if (t == null) { t = provider.get(); inScopeObjectsMap.put(key, t); } return t; } }; } public void beginNewScope() { inScopeObjectsMap = new HashMap(); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootguice-3.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.javaguice-3.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.0000644000175000017500000007346511470710026034345 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.throwingproviders; import com.google.inject.AbstractModule; import com.google.inject.Asserts; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Classes; import com.google.inject.internal.util.Function; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Iterables; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.Message; import com.google.inject.throwingproviders.ThrowingProviderBinder.Result; import java.io.IOException; import java.net.BindException; import java.rmi.AccessException; import java.rmi.RemoteException; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.TooManyListenersException; import junit.framework.TestCase; /** * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) */ public class CheckedProviderTest extends TestCase { private final TypeLiteral> remoteProviderOfString = new TypeLiteral>() { }; private final MockRemoteProvider mockRemoteProvider = new MockRemoteProvider(); private final TestScope testScope = new TestScope(); private Injector bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, String.class) .to(mockRemoteProvider) .in(testScope); } }); private Injector providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); bindScope(TestScope.Scoped.class, testScope); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) @TestScope.Scoped String throwOrGet() throws RemoteException, BindException { return mockRemoteProvider.get(); } }); public void testExceptionsThrown_Bind() throws Exception { tExceptionsThrown(bindInjector); } public void testExceptionsThrown_Provides() throws Exception { tExceptionsThrown(providesInjector); } private void tExceptionsThrown(Injector injector) throws Exception { RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.throwOnNextGet(new BindException("kaboom!")); try { remoteProvider.get(); fail(); } catch (BindException expected) { assertEquals("kaboom!", expected.getMessage()); } } public void testValuesScoped_Bind() throws Exception { tValuesScoped(bindInjector); } public void testValuesScoped_Provides() throws Exception { tValuesScoped(providesInjector); } private void tValuesScoped(Injector injector) throws Exception { RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.setNextToReturn("A"); assertEquals("A", remoteProvider.get()); mockRemoteProvider.setNextToReturn("B"); assertEquals("A", remoteProvider.get()); testScope.beginNewScope(); assertEquals("B", remoteProvider.get()); } public void testExceptionsScoped_Bind() throws Exception { tExceptionsScoped(bindInjector); } public void testExceptionsScoped_Provides() throws Exception { tExceptionsScoped(providesInjector); } private void tExceptionsScoped(Injector injector) throws Exception { RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.throwOnNextGet(new RemoteException("A")); try { remoteProvider.get(); fail(); } catch (RemoteException expected) { assertEquals("A", expected.getMessage()); } mockRemoteProvider.throwOnNextGet(new RemoteException("B")); try { remoteProvider.get(); fail(); } catch (RemoteException expected) { assertEquals("A", expected.getMessage()); } } public void testAnnotations_Bind() throws Exception { final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider(); final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider(); bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, String.class) .annotatedWith(Names.named("a")) .to(mockRemoteProviderA); ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, String.class) .to(mockRemoteProviderB); } }); tAnnotations(bindInjector, mockRemoteProviderA, mockRemoteProviderB); } public void testAnnotations_Provides() throws Exception { final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider(); final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider(); providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) @Named("a") String throwOrGet() throws RemoteException, BindException { return mockRemoteProviderA.get(); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String throwOrGet2() throws RemoteException, BindException { return mockRemoteProviderB.get(); } }); tAnnotations(providesInjector, mockRemoteProviderA, mockRemoteProviderB); } private void tAnnotations(Injector injector, MockRemoteProvider mockA, MockRemoteProvider mockB) throws Exception { mockA.setNextToReturn("A"); mockB.setNextToReturn("B"); assertEquals("A", injector.getInstance(Key.get(remoteProviderOfString, Names.named("a"))).get()); assertEquals("B", injector.getInstance(Key.get(remoteProviderOfString)).get()); } public void testUndeclaredExceptions_Bind() throws Exception { tUndeclaredExceptions(bindInjector); } public void testUndeclaredExceptions_Provides() throws Exception { tUndeclaredExceptions(providesInjector); } private void tUndeclaredExceptions(Injector injector) throws Exception { RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("A")); try { remoteProvider.get(); fail(); } catch (RuntimeException e) { assertEquals("A", e.getCause().getMessage()); } // undeclared exceptions shouldn't be scoped mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("B")); try { remoteProvider.get(); fail(); } catch (RuntimeException e) { assertEquals("B", e.getCause().getMessage()); } } public void testThrowingProviderSubclassing() throws Exception { final SubMockRemoteProvider aProvider = new SubMockRemoteProvider(); aProvider.setNextToReturn("A"); bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, String.class) .to(aProvider); } }); assertEquals("A", bindInjector.getInstance(Key.get(remoteProviderOfString)).get()); } static class SubMockRemoteProvider extends MockRemoteProvider { } public void testBindingToNonInterfaceType_Bind() throws Exception { try { Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(MockRemoteProvider.class, String.class) .to(mockRemoteProvider); } }); fail(); } catch (CreationException expected) { assertEquals(MockRemoteProvider.class.getName() + " must be an interface", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } public void testBindingToNonInterfaceType_Provides() throws Exception { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(MockRemoteProvider.class) String foo() { return null; } }); fail(); } catch (CreationException expected) { assertEquals(MockRemoteProvider.class.getName() + " must be an interface", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } public void testBindingToSubSubInterface_Bind() throws Exception { try { bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(SubRemoteProvider.class, String.class); } }); fail(); } catch (CreationException expected) { assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } public void testBindingToSubSubInterface_Provides() throws Exception { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(SubRemoteProvider.class) String foo() { return null; } }); fail(); } catch (CreationException expected) { assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } interface SubRemoteProvider extends RemoteProvider { } public void testBindingToInterfaceWithExtraMethod_Bind() throws Exception { try { bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(RemoteProviderWithExtraMethod.class, String.class); } }); fail(); } catch (CreationException expected) { assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } public void testBindingToInterfaceWithExtraMethod_Provides() throws Exception { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProviderWithExtraMethod.class) String foo() { return null; } }); fail(); } catch (CreationException expected) { assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } public void testDependencies_Bind() { bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toInstance("Foo"); bind(Integer.class).toInstance(5); bind(Double.class).toInstance(5d); bind(Long.class).toInstance(5L); ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, String.class) .to(DependentRemoteProvider.class); } }); HasDependencies hasDependencies = (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfString)); hasDependencies = (HasDependencies)bindInjector.getBinding( Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); // Make sure that that is dependent on DependentRemoteProvider. assertEquals(Dependency.get(Key.get(DependentRemoteProvider.class)), Iterables.getOnlyElement(hasDependencies.getDependencies())); // And make sure DependentRemoteProvider has the proper dependencies. hasDependencies = (HasDependencies)bindInjector.getBinding(DependentRemoteProvider.class); Set> dependencyKeys = ImmutableSet.copyOf( Iterables.transform(hasDependencies.getDependencies(), new Function, Key>() { public Key apply(Dependency from) { return from.getKey(); } })); assertEquals(ImmutableSet.>of(Key.get(String.class), Key.get(Integer.class), Key.get(Long.class), Key.get(Double.class)), dependencyKeys); } public void testDependencies_Provides() { providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toInstance("Foo"); bind(Integer.class).toInstance(5); bind(Double.class).toInstance(5d); bind(Long.class).toInstance(5L); install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo(String s, Integer i, Double d, Long l) { return null; } }); HasDependencies hasDependencies = (HasDependencies)providesInjector.getBinding(Key.get(remoteProviderOfString)); // RemoteProvider is dependent on the provider method.. hasDependencies = (HasDependencies)providesInjector.getBinding( Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); // And the provider method has our real dependencies.. hasDependencies = (HasDependencies)providesInjector.getBinding( Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); Set> dependencyKeys = ImmutableSet.copyOf( Iterables.transform(hasDependencies.getDependencies(), new Function, Key>() { public Key apply(Dependency from) { return from.getKey(); } })); assertEquals(ImmutableSet.>of(Key.get(String.class), Key.get(Integer.class), Key.get(Long.class), Key.get(Double.class)), dependencyKeys); } interface RemoteProviderWithExtraMethod extends CheckedProvider { T get(T defaultValue) throws RemoteException, BindException; } interface RemoteProvider extends CheckedProvider { public T get() throws RemoteException, BindException; } static class DependentRemoteProvider implements RemoteProvider { @Inject double foo; @Inject public DependentRemoteProvider(String foo, int bar) { } @Inject void initialize(long foo) {} public T get() throws RemoteException { return null; } } static class MockRemoteProvider implements RemoteProvider { Exception nextToThrow; T nextToReturn; public void throwOnNextGet(Exception nextToThrow) { this.nextToThrow = nextToThrow; } public void setNextToReturn(T nextToReturn) { this.nextToReturn = nextToReturn; } public T get() throws RemoteException, BindException { if (nextToThrow instanceof RemoteException) { throw (RemoteException) nextToThrow; } else if (nextToThrow instanceof BindException) { throw (BindException) nextToThrow; } else if (nextToThrow instanceof RuntimeException) { throw (RuntimeException) nextToThrow; } else if (nextToThrow == null) { return nextToReturn; } else { throw new AssertionError("nextToThrow must be a runtime or remote exception"); } } } public void testBindingToInterfaceWithBoundValueType_Bind() throws RemoteException { bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(StringRemoteProvider.class, String.class) .to(new StringRemoteProvider() { public String get() throws RemoteException { return "A"; } }); } }); assertEquals("A", bindInjector.getInstance(StringRemoteProvider.class).get()); } public void testBindingToInterfaceWithBoundValueType_Provides() throws RemoteException { providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(StringRemoteProvider.class) String foo() throws RemoteException { return "A"; } }); assertEquals("A", providesInjector.getInstance(StringRemoteProvider.class).get()); } interface StringRemoteProvider extends CheckedProvider { String get() throws RemoteException; } public void testBindingToInterfaceWithGeneric_Bind() throws Exception { bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, new TypeLiteral>() { }.getType()) .to(new RemoteProvider>() { public List get() throws RemoteException { return Arrays.asList("A", "B"); } }); } }); Key>> key = Key.get(new TypeLiteral>>() { }); assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get()); } public void testBindingToInterfaceWithGeneric_Provides() throws Exception { providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) List foo() throws RemoteException { return Arrays.asList("A", "B"); } }); Key>> key = Key.get(new TypeLiteral>>() { }); assertEquals(Arrays.asList("A", "B"), providesInjector.getInstance(key).get()); } public void testProviderMethodWithWrongException() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo() throws InterruptedException { return null; } }); fail(); } catch(CreationException ce) { assertEquals(InterruptedException.class.getName() + " is not compatible with the exceptions ([" + RemoteException.class + ", " + BindException.class + "]) declared in the CheckedProvider interface (" + RemoteProvider.class.getName() + ")", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testProviderMethodWithSubclassOfExceptionIsOk() throws Exception { providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo() throws AccessException { throw new AccessException("boo!"); } }); RemoteProvider remoteProvider = providesInjector.getInstance(Key.get(remoteProviderOfString)); try { remoteProvider.get(); fail(); } catch (RemoteException expected) { assertTrue(expected instanceof AccessException); assertEquals("boo!", expected.getMessage()); } } public void testProviderMethodWithSuperclassFails() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo() throws IOException { return null; } }); fail(); } catch(CreationException ce) { assertEquals(IOException.class.getName() + " is not compatible with the exceptions ([" + RemoteException.class + ", " + BindException.class + "]) declared in the CheckedProvider interface (" + RemoteProvider.class.getName() + ")", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testProviderMethodWithRuntimeExceptionsIsOk() throws Exception { providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo() throws RuntimeException { throw new RuntimeException("boo!"); } }); RemoteProvider remoteProvider = providesInjector.getInstance(Key.get(remoteProviderOfString)); try { remoteProvider.get(); fail(); } catch (RuntimeException expected) { assertEquals("boo!", expected.getCause().getMessage()); } } private static class SubBindException extends BindException {} public void testProviderMethodWithManyExceptions() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo() throws InterruptedException, RuntimeException, RemoteException, AccessException, TooManyListenersException, BindException, SubBindException { return null; } }); fail(); } catch(CreationException ce) { // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK. List errors = ImmutableList.copyOf(ce.getErrorMessages()); assertEquals(InterruptedException.class.getName() + " is not compatible with the exceptions ([" + RemoteException.class + ", " + BindException.class + "]) declared in the CheckedProvider interface (" + RemoteProvider.class.getName() + ")", errors.get(0).getMessage()); assertEquals(TooManyListenersException.class.getName() + " is not compatible with the exceptions ([" + RemoteException.class + ", " + BindException.class + "]) declared in the CheckedProvider interface (" + RemoteProvider.class.getName() + ")", errors.get(1).getMessage()); assertEquals(2, errors.size()); } } public void testMoreTypeParameters() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(TooManyTypeParameters.class) String foo() { return null; } }); fail(); } catch(CreationException ce) { assertEquals(TooManyTypeParameters.class.getName() + " has more than one generic type parameter: [T, P]", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testWrongThrowingProviderType() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(WrongThrowingProviderType.class) String foo() { return null; } }); fail(); } catch(CreationException ce) { assertEquals(WrongThrowingProviderType.class.getName() + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider " + "(java.lang.String) is not a generic type", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testOneMethodThatIsntGet() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(OneNoneGetMethod.class) String foo() { return null; } }); fail(); } catch(CreationException ce) { assertEquals(OneNoneGetMethod.class.getName() + " may not declare any new methods, but declared " + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]), Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testManyMethods() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(ManyMethods.class) String foo() { return null; } }); fail(); } catch(CreationException ce) { assertEquals(ManyMethods.class.getName() + " may not declare any new methods, but declared " + Arrays.asList(ManyMethods.class.getDeclaredMethods()), Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testIncorrectPredefinedType_Bind() { try { Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(StringRemoteProvider.class, Integer.class) .to(new StringRemoteProvider() { public String get() throws RemoteException { return "A"; } }); } }); fail(); } catch(CreationException ce) { assertEquals(StringRemoteProvider.class.getName() + " expects the value type to be java.lang.String, but it was java.lang.Integer", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testIncorrectPredefinedType_Provides() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(StringRemoteProvider.class) Integer foo() { return null; } }); fail(); } catch(CreationException ce) { assertEquals(StringRemoteProvider.class.getName() + " expects the value type to be java.lang.String, but it was java.lang.Integer", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } private static interface TooManyTypeParameters extends CheckedProvider { } private static interface WrongThrowingProviderType extends CheckedProvider { } private static interface OneNoneGetMethod extends CheckedProvider { T bar(); } private static interface ManyMethods extends CheckedProvider { T bar(); String baz(); } public void testResultSerializes() throws Exception { Result result = Result.forValue("foo"); result = Asserts.reserialize(result); assertEquals("foo", result.getOrThrow()); } public void testResultExceptionSerializes() throws Exception { Result result = Result.forException(new Exception("boo")); result = Asserts.reserialize(result); try { result.getOrThrow(); fail(); } catch(Exception ex) { assertEquals("boo", ex.getMessage()); } } public void testEarlyBindingError() { try { Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(StringRemoteProvider.class, String.class) .to(FailingProvider.class); } }); fail(); } catch(CreationException ce) { assertEquals("Could not find a suitable constructor in " + FailingProvider.class.getName() + ". Classes must have either one (and only one) constructor annotated with @Inject" + " or a zero-argument constructor that is not private.", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } private static class FailingProvider implements StringRemoteProvider { // no @Inject. @SuppressWarnings("unused") FailingProvider(Integer foo) {} public String get() { return null; } } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootguice-3.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/ThrowingProviderTest.javaguice-3.0/extensions/throwingproviders/test/com/google/inject/throwingproviders/ThrowingProviderTest0000644000175000017500000006750011470015316034533 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.throwingproviders; import com.google.inject.AbstractModule; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Classes; import com.google.inject.internal.util.Function; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Iterables; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.Message; import java.io.IOException; import java.rmi.AccessException; import java.rmi.RemoteException; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.TooManyListenersException; import junit.framework.TestCase; /** * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) */ @SuppressWarnings("deprecation") public class ThrowingProviderTest extends TestCase { private final TypeLiteral> remoteProviderOfString = new TypeLiteral>() { }; private final MockRemoteProvider mockRemoteProvider = new MockRemoteProvider(); private final TestScope testScope = new TestScope(); private Injector bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, String.class) .to(mockRemoteProvider) .in(testScope); } }); private Injector providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); bindScope(TestScope.Scoped.class, testScope); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) @TestScope.Scoped String throwOrGet() throws RemoteException { return mockRemoteProvider.get(); } }); public void testExceptionsThrown_Bind() { tExceptionsThrown(bindInjector); } public void testExceptionsThrown_Provides() { tExceptionsThrown(providesInjector); } private void tExceptionsThrown(Injector injector) { RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.throwOnNextGet("kaboom!"); try { remoteProvider.get(); fail(); } catch (RemoteException expected) { assertEquals("kaboom!", expected.getMessage()); } } public void testValuesScoped_Bind() throws RemoteException { tValuesScoped(bindInjector); } public void testValuesScoped_Provides() throws RemoteException { tValuesScoped(providesInjector); } private void tValuesScoped(Injector injector) throws RemoteException { RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.setNextToReturn("A"); assertEquals("A", remoteProvider.get()); mockRemoteProvider.setNextToReturn("B"); assertEquals("A", remoteProvider.get()); testScope.beginNewScope(); assertEquals("B", remoteProvider.get()); } public void testExceptionsScoped_Bind() { tExceptionsScoped(bindInjector); } public void testExceptionsScoped_Provides() { tExceptionsScoped(providesInjector); } private void tExceptionsScoped(Injector injector) { RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.throwOnNextGet("A"); try { remoteProvider.get(); fail(); } catch (RemoteException expected) { assertEquals("A", expected.getMessage()); } mockRemoteProvider.throwOnNextGet("B"); try { remoteProvider.get(); fail(); } catch (RemoteException expected) { assertEquals("A", expected.getMessage()); } } public void testAnnotations_Bind() throws RemoteException { final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider(); final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider(); bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, String.class) .annotatedWith(Names.named("a")) .to(mockRemoteProviderA); ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, String.class) .to(mockRemoteProviderB); } }); tAnnotations(bindInjector, mockRemoteProviderA, mockRemoteProviderB); } public void testAnnotations_Provides() throws RemoteException { final MockRemoteProvider mockRemoteProviderA = new MockRemoteProvider(); final MockRemoteProvider mockRemoteProviderB = new MockRemoteProvider(); providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) @Named("a") String throwOrGet() throws RemoteException { return mockRemoteProviderA.get(); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String throwOrGet2() throws RemoteException { return mockRemoteProviderB.get(); } }); tAnnotations(providesInjector, mockRemoteProviderA, mockRemoteProviderB); } private void tAnnotations(Injector injector, MockRemoteProvider mockA, MockRemoteProvider mockB) throws RemoteException { mockA.setNextToReturn("A"); mockB.setNextToReturn("B"); assertEquals("A", injector.getInstance(Key.get(remoteProviderOfString, Names.named("a"))).get()); assertEquals("B", injector.getInstance(Key.get(remoteProviderOfString)).get()); } public void testUndeclaredExceptions_Bind() throws RemoteException { tUndeclaredExceptions(bindInjector); } public void testUndeclaredExceptions_Provides() throws RemoteException { tUndeclaredExceptions(providesInjector); } private void tUndeclaredExceptions(Injector injector) throws RemoteException { RemoteProvider remoteProvider = injector.getInstance(Key.get(remoteProviderOfString)); mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("A")); try { remoteProvider.get(); fail(); } catch (RuntimeException e) { assertEquals("A", e.getCause().getMessage()); } // undeclared exceptions shouldn't be scoped mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("B")); try { remoteProvider.get(); fail(); } catch (RuntimeException e) { assertEquals("B", e.getCause().getMessage()); } } public void testThrowingProviderSubclassing() throws RemoteException { final SubMockRemoteProvider aProvider = new SubMockRemoteProvider(); aProvider.setNextToReturn("A"); bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, String.class) .to(aProvider); } }); assertEquals("A", bindInjector.getInstance(Key.get(remoteProviderOfString)).get()); } static class SubMockRemoteProvider extends MockRemoteProvider { } public void testBindingToNonInterfaceType_Bind() throws RemoteException { try { Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(MockRemoteProvider.class, String.class) .to(mockRemoteProvider); } }); fail(); } catch (CreationException expected) { assertEquals(MockRemoteProvider.class.getName() + " must be an interface", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } public void testBindingToNonInterfaceType_Provides() throws RemoteException { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(MockRemoteProvider.class) String foo() { return null; } }); fail(); } catch (CreationException expected) { assertEquals(MockRemoteProvider.class.getName() + " must be an interface", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } public void testBindingToSubSubInterface_Bind() throws RemoteException { try { bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(SubRemoteProvider.class, String.class); } }); fail(); } catch (CreationException expected) { assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } public void testBindingToSubSubInterface_Provides() throws RemoteException { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(SubRemoteProvider.class) String foo() { return null; } }); fail(); } catch (CreationException expected) { assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)", Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } interface SubRemoteProvider extends RemoteProvider { } public void testBindingToInterfaceWithExtraMethod_Bind() throws RemoteException { try { bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(RemoteProviderWithExtraMethod.class, String.class); } }); fail(); } catch (CreationException expected) { assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } public void testBindingToInterfaceWithExtraMethod_Provides() throws RemoteException { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProviderWithExtraMethod.class) String foo() { return null; } }); fail(); } catch (CreationException expected) { assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(), Iterables.getOnlyElement(expected.getErrorMessages()).getMessage()); } } public void testDependencies_Bind() { bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toInstance("Foo"); bind(Integer.class).toInstance(5); bind(Double.class).toInstance(5d); bind(Long.class).toInstance(5L); ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, String.class) .to(DependentRemoteProvider.class); } }); HasDependencies hasDependencies = (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfString)); hasDependencies = (HasDependencies)bindInjector.getBinding( Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); // Make sure that that is dependent on DependentRemoteProvider. assertEquals(Dependency.get(Key.get(DependentRemoteProvider.class)), Iterables.getOnlyElement(hasDependencies.getDependencies())); // And make sure DependentRemoteProvider has the proper dependencies. hasDependencies = (HasDependencies)bindInjector.getBinding(DependentRemoteProvider.class); Set> dependencyKeys = ImmutableSet.copyOf( Iterables.transform(hasDependencies.getDependencies(), new Function, Key>() { public Key apply(Dependency from) { return from.getKey(); } })); assertEquals(ImmutableSet.>of(Key.get(String.class), Key.get(Integer.class), Key.get(Long.class), Key.get(Double.class)), dependencyKeys); } public void testDependencies_Provides() { providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toInstance("Foo"); bind(Integer.class).toInstance(5); bind(Double.class).toInstance(5d); bind(Long.class).toInstance(5L); install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo(String s, Integer i, Double d, Long l) { return null; } }); HasDependencies hasDependencies = (HasDependencies)providesInjector.getBinding(Key.get(remoteProviderOfString)); // RemoteProvider is dependent on the provider method.. hasDependencies = (HasDependencies)providesInjector.getBinding( Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); // And the provider method has our real dependencies.. hasDependencies = (HasDependencies)providesInjector.getBinding( Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey()); Set> dependencyKeys = ImmutableSet.copyOf( Iterables.transform(hasDependencies.getDependencies(), new Function, Key>() { public Key apply(Dependency from) { return from.getKey(); } })); assertEquals(ImmutableSet.>of(Key.get(String.class), Key.get(Integer.class), Key.get(Long.class), Key.get(Double.class)), dependencyKeys); } interface RemoteProviderWithExtraMethod extends ThrowingProvider { T get(T defaultValue) throws RemoteException; } interface RemoteProvider extends ThrowingProvider { } static class DependentRemoteProvider implements RemoteProvider { @Inject double foo; @Inject public DependentRemoteProvider(String foo, int bar) { } @Inject void initialize(long foo) {} public T get() throws RemoteException { return null; } } static class MockRemoteProvider implements RemoteProvider { Exception nextToThrow; T nextToReturn; public void throwOnNextGet(String message) { throwOnNextGet(new RemoteException(message)); } public void throwOnNextGet(Exception nextToThrow) { this.nextToThrow = nextToThrow; } public void setNextToReturn(T nextToReturn) { this.nextToReturn = nextToReturn; } public T get() throws RemoteException { if (nextToThrow instanceof RemoteException) { throw (RemoteException) nextToThrow; } else if (nextToThrow instanceof RuntimeException) { throw (RuntimeException) nextToThrow; } else if (nextToThrow == null) { return nextToReturn; } else { throw new AssertionError("nextToThrow must be a runtime or remote exception"); } } } public void testBindingToInterfaceWithBoundValueType_Bind() throws RemoteException { bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(StringRemoteProvider.class, String.class) .to(new StringRemoteProvider() { public String get() throws RemoteException { return "A"; } }); } }); assertEquals("A", bindInjector.getInstance(StringRemoteProvider.class).get()); } public void testBindingToInterfaceWithBoundValueType_Provides() throws RemoteException { providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(StringRemoteProvider.class) String foo() throws RemoteException { return "A"; } }); assertEquals("A", providesInjector.getInstance(StringRemoteProvider.class).get()); } interface StringRemoteProvider extends ThrowingProvider { } public void testBindingToInterfaceWithGeneric_Bind() throws RemoteException { bindInjector = Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(RemoteProvider.class, new TypeLiteral>() { }.getType()) .to(new RemoteProvider>() { public List get() throws RemoteException { return Arrays.asList("A", "B"); } }); } }); Key>> key = Key.get(new TypeLiteral>>() { }); assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get()); } public void testBindingToInterfaceWithGeneric_Provides() throws RemoteException { providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) List foo() throws RemoteException { return Arrays.asList("A", "B"); } }); Key>> key = Key.get(new TypeLiteral>>() { }); assertEquals(Arrays.asList("A", "B"), providesInjector.getInstance(key).get()); } public void testProviderMethodWithWrongException() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo() throws InterruptedException { return null; } }); fail(); } catch(CreationException ce) { assertEquals(InterruptedException.class.getName() + " is not compatible with the exceptions ([" + RemoteException.class + "]) declared in the CheckedProvider interface (" + RemoteProvider.class.getName() + ")", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testProviderMethodWithSubclassOfExceptionIsOk() { providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo() throws AccessException { throw new AccessException("boo!"); } }); RemoteProvider remoteProvider = providesInjector.getInstance(Key.get(remoteProviderOfString)); try { remoteProvider.get(); fail(); } catch (RemoteException expected) { assertTrue(expected instanceof AccessException); assertEquals("boo!", expected.getMessage()); } } public void testProviderMethodWithSuperclassFails() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo() throws IOException { return null; } }); fail(); } catch(CreationException ce) { assertEquals(IOException.class.getName() + " is not compatible with the exceptions ([" + RemoteException.class + "]) declared in the CheckedProvider interface (" + RemoteProvider.class.getName() + ")", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testProviderMethodWithRuntimeExceptionsIsOk() throws RemoteException { providesInjector = Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo() throws RuntimeException { throw new RuntimeException("boo!"); } }); RemoteProvider remoteProvider = providesInjector.getInstance(Key.get(remoteProviderOfString)); try { remoteProvider.get(); fail(); } catch (RuntimeException expected) { assertEquals("boo!", expected.getCause().getMessage()); } } public void testProviderMethodWithManyExceptions() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(RemoteProvider.class) String foo() throws InterruptedException, RuntimeException, RemoteException, AccessException, TooManyListenersException { return null; } }); fail(); } catch(CreationException ce) { // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK. List errors = ImmutableList.copyOf(ce.getErrorMessages()); assertEquals(InterruptedException.class.getName() + " is not compatible with the exceptions ([" + RemoteException.class + "]) declared in the CheckedProvider interface (" + RemoteProvider.class.getName() + ")", errors.get(0).getMessage()); assertEquals(TooManyListenersException.class.getName() + " is not compatible with the exceptions ([" + RemoteException.class + "]) declared in the CheckedProvider interface (" + RemoteProvider.class.getName() + ")", errors.get(1).getMessage()); assertEquals(2, errors.size()); } } public void testMoreTypeParameters() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(TooManyTypeParameters.class) String foo() { return null; } }); fail(); } catch(CreationException ce) { assertEquals(TooManyTypeParameters.class.getName() + " has more than one generic type parameter: [T, P]", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testWrongThrowingProviderType() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(WrongThrowingProviderType.class) String foo() { return null; } }); fail(); } catch(CreationException ce) { assertEquals(WrongThrowingProviderType.class.getName() + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider " + "(java.lang.String) is not a generic type", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testOneMethodThatIsntGet() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(OneNoneGetMethod.class) String foo() { return null; } }); fail(); } catch(CreationException ce) { assertEquals(OneNoneGetMethod.class.getName() + " may not declare any new methods, but declared " + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]), Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testManyMethods() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(ManyMethods.class) String foo() { return null; } }); fail(); } catch(CreationException ce) { assertEquals(ManyMethods.class.getName() + " may not declare any new methods, but declared " + Arrays.asList(ManyMethods.class.getDeclaredMethods()), Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testIncorrectPredefinedType_Bind() { try { Guice.createInjector(new AbstractModule() { protected void configure() { ThrowingProviderBinder.create(binder()) .bind(StringRemoteProvider.class, Integer.class) .to(new StringRemoteProvider() { public String get() throws RemoteException { return "A"; } }); } }); fail(); } catch(CreationException ce) { assertEquals(StringRemoteProvider.class.getName() + " expects the value type to be java.lang.String, but it was java.lang.Integer", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } public void testIncorrectPredefinedType_Provides() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(ThrowingProviderBinder.forModule(this)); } @SuppressWarnings("unused") @CheckedProvides(StringRemoteProvider.class) Integer foo() { return null; } }); fail(); } catch(CreationException ce) { assertEquals(StringRemoteProvider.class.getName() + " expects the value type to be java.lang.String, but it was java.lang.Integer", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } private static interface TooManyTypeParameters extends ThrowingProvider { } private static interface WrongThrowingProviderType extends ThrowingProvider { } private static interface OneNoneGetMethod extends ThrowingProvider { T bar(); } private static interface ManyMethods extends ThrowingProvider { T bar(); String baz(); } } guice-3.0/extensions/throwingproviders/src/0000755000175000017500000000000011214265006021126 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/src/com/0000755000175000017500000000000011214265006021704 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/src/com/google/0000755000175000017500000000000011214265006023160 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/src/com/google/inject/0000755000175000017500000000000011214265006024434 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/0000755000175000017500000000000011502214670030234 5ustar drazzibdrazzibguice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/package-info.java0000644000175000017500000000142111461123622033421 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Extension for injecting objects that may throw at provision time; this extension requires {@code * guice-throwingproviders-3.0.jar}. */ package com.google.inject.throwingproviders;././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootguice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.javaguice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinde0000644000175000017500000003277311475262660034464 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.throwingproviders; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.binder.ScopedBindingBuilder; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.internal.UniqueAnnotations; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import com.google.inject.spi.Dependency; import com.google.inject.spi.ProviderWithDependencies; import com.google.inject.util.Types; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.Arrays; import java.util.List; import java.util.Set; /** *

Builds a binding for a {@link CheckedProvider}. * *

You can use a fluent API and custom providers: *

ThrowingProviderBinder.create(binder())
 *    .bind(RemoteProvider.class, Customer.class)
 *    .to(RemoteCustomerProvider.class)
 *    .in(RequestScope.class);
 * 
* or, you can use throwing provider methods: *
class MyModule extends AbstractModule {
 *   configure() {
 *     ThrowingProviderBinder.install(this, binder());
 *   }
 *   
 *   {@literal @}CheckedProvides(RemoteProvider.class)
 *   {@literal @}RequestScope
 *   Customer provideCustomer(FlakyCustomerCreator creator) throws RemoteException {
 *     return creator.getCustomerOrThrow();
 *   }
 * }
 * 
* * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) */ public class ThrowingProviderBinder { private final Binder binder; private ThrowingProviderBinder(Binder binder) { this.binder = binder; } public static ThrowingProviderBinder create(Binder binder) { return new ThrowingProviderBinder(binder.skipSources( ThrowingProviderBinder.class, ThrowingProviderBinder.SecondaryBinder.class)); } /** * Returns a module that installs {@literal @}{@link CheckedProvides} methods. * * @since 3.0 */ public static Module forModule(Module module) { return CheckedProviderMethodsModule.forModule(module); } public

SecondaryBinder

bind(final Class

interfaceType, final Type valueType) { return new SecondaryBinder

(interfaceType, valueType); } public class SecondaryBinder

{ private final Class

interfaceType; private final Type valueType; private final List> exceptionTypes; private final boolean valid; private Class annotationType; private Annotation annotation; private Key

interfaceKey; public SecondaryBinder(Class

interfaceType, Type valueType) { this.interfaceType = checkNotNull(interfaceType, "interfaceType"); this.valueType = checkNotNull(valueType, "valueType"); if(checkInterface()) { this.exceptionTypes = getExceptionType(interfaceType); valid = true; } else { valid = false; this.exceptionTypes = ImmutableList.of(); } } List> getExceptionTypes() { return exceptionTypes; } Key

getKey() { return interfaceKey; } public SecondaryBinder

annotatedWith(Class annotationType) { if (!(this.annotationType == null && this.annotation == null)) { throw new IllegalStateException(); } this.annotationType = annotationType; return this; } public SecondaryBinder

annotatedWith(Annotation annotation) { if (!(this.annotationType == null && this.annotation == null)) { throw new IllegalStateException(); } this.annotation = annotation; return this; } public ScopedBindingBuilder to(P target) { Key

targetKey = Key.get(interfaceType, UniqueAnnotations.create()); binder.bind(targetKey).toInstance(target); return to(targetKey); } public ScopedBindingBuilder to(Class targetType) { return to(Key.get(targetType)); } ScopedBindingBuilder toProviderMethod(CheckedProviderMethod target) { Key targetKey = Key.get(CheckedProviderMethod.class, UniqueAnnotations.create()); binder.bind(targetKey).toInstance(target); return toInternal(targetKey); } public ScopedBindingBuilder to(Key targetKey) { checkNotNull(targetKey, "targetKey"); return toInternal(targetKey); } private ScopedBindingBuilder toInternal(final Key targetKey) { final Key resultKey = Key.get(Result.class, UniqueAnnotations.create()); final Provider resultProvider = binder.getProvider(resultKey); final Provider targetProvider = binder.getProvider(targetKey); interfaceKey = createKey(); // don't bother binding the proxy type if this is in an invalid state. if(valid) { binder.bind(interfaceKey).toProvider(new ProviderWithDependencies

() { private final P instance = interfaceType.cast(Proxy.newProxyInstance( interfaceType.getClassLoader(), new Class[] { interfaceType }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return resultProvider.get().getOrThrow(); } })); public P get() { return instance; } public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(resultKey)); } }); } return binder.bind(resultKey).toProvider(new ProviderWithDependencies() { public Result get() { try { return Result.forValue(targetProvider.get().get()); } catch (Exception e) { for(Class exceptionType : exceptionTypes) { if (exceptionType.isInstance(e)) { return Result.forException(e); } } if (e instanceof RuntimeException) { throw (RuntimeException) e; } else { // this should never happen throw new RuntimeException(e); } } } public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(targetKey)); } }); } /** * Returns the exception type declared to be thrown by the get method of * {@code interfaceType}. */ private List> getExceptionType(Class

interfaceType) { try { Method getMethod = interfaceType.getMethod("get"); List> exceptionLiterals = TypeLiteral.get(interfaceType).getExceptionTypes(getMethod); List> results = Lists.newArrayList(); for (TypeLiteral exLiteral : exceptionLiterals) { results.add(exLiteral.getRawType().asSubclass(Throwable.class)); } return results; } catch (SecurityException e) { throw new IllegalStateException("Not allowed to inspect exception types", e); } catch (NoSuchMethodException e) { throw new IllegalStateException("No 'get'method available", e); } } private boolean checkInterface() { if(!checkArgument(interfaceType.isInterface(), "%s must be an interface", interfaceType.getName())) { return false; } if(!checkArgument(interfaceType.getGenericInterfaces().length == 1, "%s must extend CheckedProvider (and only CheckedProvider)", interfaceType)) { return false; } boolean tpMode = interfaceType.getInterfaces()[0] == ThrowingProvider.class; if(!tpMode) { if(!checkArgument(interfaceType.getInterfaces()[0] == CheckedProvider.class, "%s must extend CheckedProvider (and only CheckedProvider)", interfaceType)) { return false; } } // Ensure that T is parameterized and unconstrained. ParameterizedType genericThrowingProvider = (ParameterizedType) interfaceType.getGenericInterfaces()[0]; if (interfaceType.getTypeParameters().length == 1) { String returnTypeName = interfaceType.getTypeParameters()[0].getName(); Type returnType = genericThrowingProvider.getActualTypeArguments()[0]; if(!checkArgument(returnType instanceof TypeVariable, "%s does not properly extend CheckedProvider, the first type parameter of CheckedProvider (%s) is not a generic type", interfaceType, returnType)) { return false; } if(!checkArgument(returnTypeName.equals(((TypeVariable) returnType).getName()), "The generic type (%s) of %s does not match the generic type of CheckedProvider (%s)", returnTypeName, interfaceType, ((TypeVariable)returnType).getName())) { return false; } } else { if(!checkArgument(interfaceType.getTypeParameters().length == 0, "%s has more than one generic type parameter: %s", interfaceType, Arrays.asList(interfaceType.getTypeParameters()))) { return false; } if(!checkArgument(genericThrowingProvider.getActualTypeArguments()[0].equals(valueType), "%s expects the value type to be %s, but it was %s", interfaceType, genericThrowingProvider.getActualTypeArguments()[0], valueType)) { return false; } } if(tpMode) { // only validate exception in ThrowingProvider mode. Type exceptionType = genericThrowingProvider.getActualTypeArguments()[1]; if(!checkArgument(exceptionType instanceof Class, "%s has the wrong Exception generic type (%s) when extending CheckedProvider", interfaceType, exceptionType)) { return false; } } if (interfaceType.getDeclaredMethods().length == 1) { Method method = interfaceType.getDeclaredMethods()[0]; if(!checkArgument(method.getName().equals("get"), "%s may not declare any new methods, but declared %s", interfaceType, method)) { return false; } if(!checkArgument(method.getParameterTypes().length == 0, "%s may not declare any new methods, but declared %s", interfaceType, method.toGenericString())) { return false; } } else { if(!checkArgument(interfaceType.getDeclaredMethods().length == 0, "%s may not declare any new methods, but declared %s", interfaceType, Arrays.asList(interfaceType.getDeclaredMethods()))) { return false; } } return true; } private boolean checkArgument(boolean condition, String messageFormat, Object... args) { if (!condition) { binder.addError(messageFormat, args); return false; } else { return true; } } @SuppressWarnings({"unchecked"}) private Key

createKey() { TypeLiteral

typeLiteral; if (interfaceType.getTypeParameters().length == 1) { ParameterizedType type = Types.newParameterizedTypeWithOwner( interfaceType.getEnclosingClass(), interfaceType, valueType); typeLiteral = (TypeLiteral

) TypeLiteral.get(type); } else { typeLiteral = TypeLiteral.get(interfaceType); } if (annotation != null) { return Key.get(typeLiteral, annotation); } else if (annotationType != null) { return Key.get(typeLiteral, annotationType); } else { return Key.get(typeLiteral); } } } /** * Represents the returned value from a call to {@link * CheckedProvider#get()}. This is the value that will be scoped by Guice. */ static class Result implements Serializable { private final Object value; private final Exception exception; private Result(Object value, Exception exception) { this.value = value; this.exception = exception; } public static Result forValue(Object value) { return new Result(value, null); } public static Result forException(Exception e) { return new Result(null, e); } public Object getOrThrow() throws Exception { if (exception != null) { throw exception; } else { return value; } } private static final long serialVersionUID = 0L; } } guice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvides.java0000644000175000017500000000312711475262660034157 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.throwingproviders; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Annotates methods of a {@link Module} to create a {@link CheckedProvider} * method binding that can throw exceptions. The method's return type is bound * to a {@link CheckedProvider} that can be injected. Guice will pass * dependencies to the method as parameters. Install {@literal @}CheckedProvides * methods by using * {@link ThrowingProviderBinder#forModule(com.google.inject.Module)} on the * module where the methods are declared. * * @author sameb@google.com (Sam Berlin) * @since 3.0 */ @Documented @Target(METHOD) @Retention(RUNTIME) public @interface CheckedProvides { /** * The interface that provides this value, a subinterface of {@link CheckedProvider}. */ Class value(); } guice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvider.java0000644000175000017500000000263411471310214034141 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.throwingproviders; /** * Alternative to the Guice {@link com.google.inject.Provider} that throws * a checked Exception. Users may not inject {@code T} directly. * *

This interface must be extended to use application-specific exception types. * Such subinterfaces may not define new methods, but may narrow the exception type. *

 * public interface RemoteProvider<T> extends CheckedProvider<T> { 
 *   T get() throws CustomExceptionOne, CustomExceptionTwo;
 * }
 * 
* *

When this type is bound using {@link ThrowingProviderBinder}, the value returned * or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get} * will invoked at most once within each scope. * * @since 3.0 */ public interface CheckedProvider { T get() throws Exception; } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootguice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.javaguice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod0000644000175000017500000001244411502214670034366 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.throwingproviders; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.Set; import com.google.inject.Binder; import com.google.inject.Exposed; import com.google.inject.Key; import com.google.inject.PrivateBinder; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.binder.ScopedBindingBuilder; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.StackTraceElements; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder; /** * A provider that invokes a method and returns its result. * * @author sameb@google.com (Sam Berlin) */ class CheckedProviderMethod implements CheckedProvider, HasDependencies { private final Key key; private final Class scopeAnnotation; private final Object instance; private final Method method; private final ImmutableSet> dependencies; private final List> parameterProviders; private final boolean exposed; private final Class checkedProvider; private final List> exceptionTypes; CheckedProviderMethod( Key key, Method method, Object instance, ImmutableSet> dependencies, List> parameterProviders, Class scopeAnnotation, Class checkedProvider, List> exceptionTypes) { this.key = key; this.scopeAnnotation = scopeAnnotation; this.instance = instance; this.dependencies = dependencies; this.method = method; this.parameterProviders = parameterProviders; this.exposed = method.isAnnotationPresent(Exposed.class); this.checkedProvider = checkedProvider; this.exceptionTypes = exceptionTypes; method.setAccessible(true); } void configure(Binder binder) { binder = binder.withSource(method); SecondaryBinder sbinder = ThrowingProviderBinder.create(binder) .bind(checkedProvider, key.getTypeLiteral().getType()); if(key.getAnnotation() != null) { sbinder = sbinder.annotatedWith(key.getAnnotation()); } else if(key.getAnnotationType() != null) { sbinder = sbinder.annotatedWith(key.getAnnotationType()); } ScopedBindingBuilder sbbuilder = sbinder.toProviderMethod(this); if(scopeAnnotation != null) { sbbuilder.in(scopeAnnotation); } if (exposed) { // the cast is safe 'cause the only binder we have implements PrivateBinder. If there's a // misplaced @Exposed, calling this will add an error to the binder's error queue ((PrivateBinder) binder).expose(sbinder.getKey()); } // Validate the exceptions in the method match the exceptions // in the CheckedProvider. for(TypeLiteral exType : exceptionTypes) { Class exActual = exType.getRawType(); // Ignore runtime exceptions & errors. if(RuntimeException.class.isAssignableFrom(exActual) || Error.class.isAssignableFrom(exActual)) { continue; } boolean notAssignable = true; for(Class exExpected : sbinder.getExceptionTypes()) { if (exExpected.isAssignableFrom(exActual)) { notAssignable = false; break; } } if(notAssignable) { binder.addError( "%s is not compatible with the exceptions (%s) declared in the CheckedProvider interface (%s)", exActual, sbinder.getExceptionTypes(), checkedProvider); } } } public T get() throws Exception { Object[] parameters = new Object[parameterProviders.size()]; for (int i = 0; i < parameters.length; i++) { parameters[i] = parameterProviders.get(i).get(); } try { // We know this cast is safe becase T is the method's return type. @SuppressWarnings({ "unchecked", "UnnecessaryLocalVariable" }) T result = (T) method.invoke(instance, parameters); return result; } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if(t instanceof Exception) { throw (Exception)t; } else if(t instanceof Error) { throw (Error)t; } else { throw new IllegalStateException(t); } } } public Set> getDependencies() { return dependencies; } @Override public String toString() { return "@CheckedProvides " + StackTraceElements.forMember(method).toString(); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootguice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.javaguice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod0000644000175000017500000001360411475262660034400 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.throwingproviders; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.internal.Annotations; import com.google.inject.internal.Errors; import com.google.inject.internal.UniqueAnnotations; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.spi.Dependency; import com.google.inject.spi.Message; import com.google.inject.util.Modules; import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.List; import java.util.logging.Logger; /** * Creates bindings to methods annotated with {@literal @}{@link CheckedProvides}. Use the scope * and binding annotations on the provider method to configure the binding. * * @author sameb@google.com (Sam Berlin) */ final class CheckedProviderMethodsModule implements Module { private final Object delegate; private final TypeLiteral typeLiteral; private CheckedProviderMethodsModule(Object delegate) { this.delegate = checkNotNull(delegate, "delegate"); this.typeLiteral = TypeLiteral.get(this.delegate.getClass()); } /** * Returns a module which creates bindings for provider methods from the given module. */ static Module forModule(Module module) { // avoid infinite recursion, since installing a module always installs itself if (module instanceof CheckedProviderMethodsModule) { return Modules.EMPTY_MODULE; } return new CheckedProviderMethodsModule(module); } public synchronized void configure(Binder binder) { for (CheckedProviderMethod throwingProviderMethod : getProviderMethods(binder)) { throwingProviderMethod.configure(binder); } } List> getProviderMethods(Binder binder) { List> result = Lists.newArrayList(); for (Class c = delegate.getClass(); c != Object.class; c = c.getSuperclass()) { for (Method method : c.getDeclaredMethods()) { CheckedProvides checkedProvides = (CheckedProvides)method.getAnnotation(CheckedProvides.class); if(checkedProvides != null) { result.add(createProviderMethod(binder, method, checkedProvides.value())); } } } return result; } CheckedProviderMethod createProviderMethod(Binder binder, final Method method, Class throwingProvider) { binder = binder.withSource(method); Errors errors = new Errors(method); // prepare the parameter providers List> dependencies = Lists.newArrayList(); List> parameterProviders = Lists.newArrayList(); List> parameterTypes = typeLiteral.getParameterTypes(method); Annotation[][] parameterAnnotations = method.getParameterAnnotations(); for (int i = 0; i < parameterTypes.size(); i++) { Key key = getKey(errors, parameterTypes.get(i), method, parameterAnnotations[i]); if(key.equals(Key.get(Logger.class))) { // If it was a Logger, change the key to be unique & bind it to a // provider that provides a logger with a proper name. // This solves issue 482 (returning a new anonymous logger on every call exhausts memory) Key loggerKey = Key.get(Logger.class, UniqueAnnotations.create()); binder.bind(loggerKey).toProvider(new LogProvider(method)); key = loggerKey; } dependencies.add(Dependency.get(key)); parameterProviders.add(binder.getProvider(key)); } @SuppressWarnings("unchecked") // Define T as the method's return type. TypeLiteral returnType = (TypeLiteral) typeLiteral.getReturnType(method); List> exceptionTypes = typeLiteral.getExceptionTypes(method); Key key = getKey(errors, returnType, method, method.getAnnotations()); Class scopeAnnotation = Annotations.findScopeAnnotation(errors, method.getAnnotations()); for (Message message : errors.getMessages()) { binder.addError(message); } return new CheckedProviderMethod(key, method, delegate, ImmutableSet.copyOf(dependencies), parameterProviders, scopeAnnotation, throwingProvider, exceptionTypes); } Key getKey(Errors errors, TypeLiteral type, Member member, Annotation[] annotations) { Annotation bindingAnnotation = Annotations.findBindingAnnotation(errors, member, annotations); return bindingAnnotation == null ? Key.get(type) : Key.get(type, bindingAnnotation); } @Override public boolean equals(Object o) { return o instanceof CheckedProviderMethodsModule && ((CheckedProviderMethodsModule) o).delegate == delegate; } @Override public int hashCode() { return delegate.hashCode(); } /** A provider that returns a logger based on the method name. */ private static final class LogProvider implements Provider { private final String name; public LogProvider(Method method) { this.name = method.getDeclaringClass().getName() + "." + method.getName(); } public Logger get() { return Logger.getLogger(name); } } } guice-3.0/extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProvider.java0000644000175000017500000000300511467716460034427 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.throwingproviders; /** * Alternative to the Guice {@link com.google.inject.Provider} that throws * a checked Exception. Users may not inject {@code T} directly. * *

This interface must be extended to use application-specific exception types. * Such subinterfaces may not define new methods: *

 * public interface RemoteProvider<T> extends ThrowingProvider<T, RemoteException> { }
 * 
* *

When this type is bound using {@link ThrowingProviderBinder}, the value returned * or exception thrown by {@link #get} will be scoped. As a consequence, {@link #get} * will invoked at most once within each scope. * * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) * @deprecated use {@link CheckedProvider} instead. */ @Deprecated public interface ThrowingProvider extends CheckedProvider { T get() throws E; } guice-3.0/extensions/servlet/0000755000175000017500000000000011542727750016241 5ustar drazzibdrazzibguice-3.0/extensions/servlet/build/0000755000175000017500000000000011542727750017340 5ustar drazzibdrazzibguice-3.0/extensions/servlet/build/META-INF/0000755000175000017500000000000011542727750020500 5ustar drazzibdrazzibguice-3.0/extensions/servlet/build/META-INF/MANIFEST.MF0000644000175000017500000000126311542727746022141 0ustar drazzibdrazzibManifest-Version: 1.0 Export-Package: com.google.inject.servlet;version="1.3" Bundle-Name: guice-servlet Created-By: 1.6.0_23 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-Copyright: Copyright (C) 2006 Google Inc. Bundle-Vendor: Google, Inc. Fragment-Host: com.google.inject Bundle-Version: 3.0 Bundle-ManifestVersion: 2 Bundle-Description: Guice is a lightweight dependency injection framew ork for Java 5 and above Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-DocURL: http://code.google.com/p/google-guice/ Bundle-SymbolicName: com.google.inject.servlet Import-Package: javax.servlet,javax.servlet.http guice-3.0/extensions/servlet/build/dist/0000755000175000017500000000000011542727750020303 5ustar drazzibdrazzibguice-3.0/extensions/servlet/build/classes/0000755000175000017500000000000011542727750020775 5ustar drazzibdrazzibguice-3.0/extensions/servlet/build/classes/com/0000755000175000017500000000000011542727750021553 5ustar drazzibdrazzibguice-3.0/extensions/servlet/build/classes/com/google/0000755000175000017500000000000011542727750023027 5ustar drazzibdrazzibguice-3.0/extensions/servlet/build/classes/com/google/inject/0000755000175000017500000000000011542727750024303 5ustar drazzibdrazzibguice-3.0/extensions/servlet/build/classes/com/google/inject/servlet/0000755000175000017500000000000011542727750025767 5ustar drazzibdrazzibguice-3.0/extensions/servlet/pom.xml0000644000175000017500000000167311464433216017557 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-servlet Google Guice - Extensions - Servlet javax.servlet servlet-api 2.5 provided org.easymock easymock 3.0 test guice-3.0/extensions/servlet/build.xml0000644000175000017500000000141711461503364020056 0ustar drazzibdrazzib guice-3.0/extensions/servlet/lib/0000755000175000017500000000000011434007750016776 5ustar drazzibdrazzibguice-3.0/extensions/servlet/lib/build/0000755000175000017500000000000011434007750020075 5ustar drazzibdrazzibguice-3.0/extensions/servlet/build.properties0000644000175000017500000000025111461376774021462 0ustar drazzibdrazziblib.dir=../../lib ext.lib.dir=lib src.dir=src test.dir=test build.dir=build test.class=com.google.inject.servlet.AllTests module=com.google.inject.servlet fragment=true guice-3.0/extensions/servlet/test/0000755000175000017500000000000011434007752017211 5ustar drazzibdrazzibguice-3.0/extensions/servlet/test/com/0000755000175000017500000000000011434007752017767 5ustar drazzibdrazzibguice-3.0/extensions/servlet/test/com/google/0000755000175000017500000000000011434007752021243 5ustar drazzibdrazzibguice-3.0/extensions/servlet/test/com/google/inject/0000755000175000017500000000000011434007752022517 5ustar drazzibdrazzibguice-3.0/extensions/servlet/test/com/google/inject/servlet/0000755000175000017500000000000011542577562024216 5ustar drazzibdrazzibguice-3.0/extensions/servlet/test/com/google/inject/servlet/InjectedFilterPipelineTest.java0000644000175000017500000001330311542576630032275 0ustar drazzibdrazzibpackage com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import junit.framework.TestCase; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.isA; import static org.easymock.EasyMock.isNull; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.reset; import static org.easymock.EasyMock.verify; /** * Exactly the same as {@linkplain com.google.inject.servlet.FilterPipelineTest} except * that we test that the static pipeline is not used. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class InjectedFilterPipelineTest extends TestCase { private Injector injector1; private Injector injector2; @Override public final void setUp() { injector1 = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filter("/*").through(TestFilter.class); filter("*.html").through(TestFilter.class); filter("/*").through(Key.get(TestFilter.class)); filter("*.jsp").through(Key.get(TestFilter.class)); // These filters should never fire filter("/index/*").through(Key.get(NeverFilter.class)); filter("/public/login/*").through(Key.get(NeverFilter.class)); } }); // Test second injector with exactly opposite pipeline config injector2 = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { // These filters should never fire filter("*.html").through(NeverFilter.class); filter("/non-jsp/*").through(Key.get(NeverFilter.class)); // only these filters fire. filter("/index/*").through(Key.get(TestFilter.class)); filter("/public/login/*").through(Key.get(TestFilter.class)); } }); } @Override public final void tearDown() { } public final void testDispatchThruInjectedGuiceFilter() throws ServletException, IOException { //create mocks FilterConfig filterConfig = createMock(FilterConfig.class); ServletContext servletContext = createMock(ServletContext.class); HttpServletRequest request = createMock(HttpServletRequest.class); FilterChain proceedingFilterChain = createMock(FilterChain.class); //begin mock script *** expect(filterConfig.getServletContext()) .andReturn(servletContext) .once(); expect(request.getRequestURI()) .andReturn("/non-jsp/login.html") // use a path that will fail in injector2 .anyTimes(); expect(request.getContextPath()) .andReturn("") .anyTimes(); //at the end, proceed down webapp's normal filter chain proceedingFilterChain.doFilter(isA(HttpServletRequest.class), (ServletResponse) isNull()); expectLastCall().once(); //run mock script *** replay(filterConfig, servletContext, request, proceedingFilterChain); GuiceFilter webFilter = injector1.getInstance(GuiceFilter.class); webFilter.init(filterConfig); webFilter.doFilter(request, null, proceedingFilterChain); webFilter.destroy(); //assert expectations verify(filterConfig, servletContext, request, proceedingFilterChain); // reset mocks and run them against the other injector reset(filterConfig, servletContext, request, proceedingFilterChain); // Create a second proceeding filter chain FilterChain proceedingFilterChain2 = createMock(FilterChain.class); //begin mock script *** expect(filterConfig.getServletContext()) .andReturn(servletContext) .once(); expect(request.getRequestURI()) .andReturn("/public/login/login.jsp") // use a path that will fail in injector1 .anyTimes(); expect(request.getContextPath()) .andReturn("") .anyTimes(); //at the end, proceed down webapp's normal filter chain proceedingFilterChain2.doFilter(isA(HttpServletRequest.class), (ServletResponse) isNull()); expectLastCall().once(); // Never fire on this pipeline replay(filterConfig, servletContext, request, proceedingFilterChain2, proceedingFilterChain); webFilter = injector2.getInstance(GuiceFilter.class); webFilter.init(filterConfig); webFilter.doFilter(request, null, proceedingFilterChain2); webFilter.destroy(); // Verify that we have not crossed the streams, Venkman! verify(filterConfig, servletContext, request, proceedingFilterChain, proceedingFilterChain2); } @Singleton public static class TestFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } public void destroy() { } } @Singleton public static class NeverFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { fail("This filter should never have fired"); } public void destroy() { } } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionPathsTest.java0000644000175000017500000002720611434212566032353 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Binding; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.internal.util.Maps; import com.google.inject.internal.util.Sets; import com.google.inject.spi.BindingScopingVisitor; import java.io.IOException; import java.util.HashMap; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; /** * Ensures servlet spec compliance for CGI-style variables and general * path/pattern matching. * * @author Dhanji R. Prasanna (dhanji@gmail com) */ public class ServletDefinitionPathsTest extends TestCase { // Data-driven test. public final void testServletPathMatching() throws IOException, ServletException { servletPath("/index.html", "*.html", "/index.html"); servletPath("/somewhere/index.html", "*.html", "/somewhere/index.html"); servletPath("/somewhere/index.html", "/*", ""); servletPath("/index.html", "/*", ""); servletPath("/", "/*", ""); servletPath("//", "/*", ""); servletPath("/////", "/*", ""); servletPath("", "/*", ""); servletPath("/thing/index.html", "/thing/*", "/thing"); servletPath("/thing/wing/index.html", "/thing/*", "/thing"); } private void servletPath(final String requestPath, String mapping, final String expectedServletPath) throws IOException, ServletException { Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); HttpServletRequest request = createMock(HttpServletRequest.class); HttpServletResponse response = createMock(HttpServletResponse.class); expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) .andReturn(true); expect(injector.getBinding(Key.get(HttpServlet.class))) .andReturn(binding); final boolean[] run = new boolean[1]; //get an instance of this servlet expect(injector.getInstance(Key.get(HttpServlet.class))) .andReturn(new HttpServlet() { @Override protected void service(HttpServletRequest servletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { final String path = servletRequest.getServletPath(); assertEquals(String.format("expected [%s] but was [%s]", expectedServletPath, path), expectedServletPath, path); run[0] = true; } }); expect(request.getServletPath()) .andReturn(requestPath); replay(injector, binding, request); ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, mapping), new HashMap(), null); servletDefinition.init(null, injector, Sets.newSetFromMap(Maps.newIdentityHashMap())); servletDefinition.doService(request, response); assertTrue("Servlet did not run!", run[0]); verify(injector, binding, request); } // Data-driven test. public final void testPathInfoWithServletStyleMatching() throws IOException, ServletException { pathInfoWithServletStyleMatching("/path/index.html", "/path", "/*", "/index.html", ""); pathInfoWithServletStyleMatching("/path//hulaboo///index.html", "/path", "/*", "/hulaboo/index.html", ""); pathInfoWithServletStyleMatching("/path/", "/path", "/*", "/", ""); pathInfoWithServletStyleMatching("/path////////", "/path", "/*", "/", ""); // a servlet mapping of /thing/* pathInfoWithServletStyleMatching("/path/thing////////", "/path", "/thing/*", "/", "/thing"); pathInfoWithServletStyleMatching("/path/thing/stuff", "/path", "/thing/*", "/stuff", "/thing"); pathInfoWithServletStyleMatching("/path/thing/stuff.html", "/path", "/thing/*", "/stuff.html", "/thing"); pathInfoWithServletStyleMatching("/path/thing", "/path", "/thing/*", null, "/thing"); // *.xx style mapping pathInfoWithServletStyleMatching("/path/thing.thing", "/path", "*.thing", null, "/thing.thing"); pathInfoWithServletStyleMatching("/path///h.thing", "/path", "*.thing", null, "/h.thing"); pathInfoWithServletStyleMatching("/path///...//h.thing", "/path", "*.thing", null, "/.../h.thing"); pathInfoWithServletStyleMatching("/path/my/h.thing", "/path", "*.thing", null, "/my/h.thing"); } private void pathInfoWithServletStyleMatching(final String requestUri, final String contextPath, String mapping, final String expectedPathInfo, final String servletPath) throws IOException, ServletException { Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); HttpServletRequest request = createMock(HttpServletRequest.class); HttpServletResponse response = createMock(HttpServletResponse.class); expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) .andReturn(true); expect(injector.getBinding(Key.get(HttpServlet.class))) .andReturn(binding); final boolean[] run = new boolean[1]; //get an instance of this servlet expect(injector.getInstance(Key.get(HttpServlet.class))) .andReturn(new HttpServlet() { @Override protected void service(HttpServletRequest servletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { final String path = servletRequest.getPathInfo(); if (null == expectedPathInfo) { assertNull(String.format("expected [%s] but was [%s]", expectedPathInfo, path), path); } else { assertEquals(String.format("expected [%s] but was [%s]", expectedPathInfo, path), expectedPathInfo, path); } //assert memoizer //noinspection StringEquality assertSame("memo field did not work", path, servletRequest.getPathInfo()); run[0] = true; } }); expect(request.getRequestURI()) .andReturn(requestUri); expect(request.getServletPath()) .andReturn(servletPath) .anyTimes(); expect(request.getContextPath()) .andReturn(contextPath); expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null); replay(injector, binding, request); ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, mapping), new HashMap(), null); servletDefinition.init(null, injector, Sets.newSetFromMap(Maps.newIdentityHashMap())); servletDefinition.doService(request, response); assertTrue("Servlet did not run!", run[0]); verify(injector, binding, request); } // Data-driven test. public final void testPathInfoWithRegexMatching() throws IOException, ServletException { // first a mapping of /* pathInfoWithRegexMatching("/path/index.html", "/path", "/(.)*", "/index.html", ""); pathInfoWithRegexMatching("/path//hulaboo///index.html", "/path", "/(.)*", "/hulaboo/index.html", ""); pathInfoWithRegexMatching("/path/", "/path", "/(.)*", "/", ""); pathInfoWithRegexMatching("/path////////", "/path", "/(.)*", "/", ""); // a servlet mapping of /thing/* pathInfoWithRegexMatching("/path/thing////////", "/path", "/thing/(.)*", "/", "/thing"); pathInfoWithRegexMatching("/path/thing/stuff", "/path", "/thing/(.)*", "/stuff", "/thing"); pathInfoWithRegexMatching("/path/thing/stuff.html", "/path", "/thing/(.)*", "/stuff.html", "/thing"); pathInfoWithRegexMatching("/path/thing", "/path", "/thing/(.)*", null, "/thing"); // *.xx style mapping pathInfoWithRegexMatching("/path/thing.thing", "/path", ".*\\.thing", null, "/thing.thing"); pathInfoWithRegexMatching("/path///h.thing", "/path", ".*\\.thing", null, "/h.thing"); pathInfoWithRegexMatching("/path///...//h.thing", "/path", ".*\\.thing", null, "/.../h.thing"); pathInfoWithRegexMatching("/path/my/h.thing", "/path", ".*\\.thing", null, "/my/h.thing"); // path pathInfoWithRegexMatching("/path/test.com/com.test.MyServletModule", "", "/path/[^/]+/(.*)", "com.test.MyServletModule", "/path/test.com/com.test.MyServletModule"); } public final void pathInfoWithRegexMatching(final String requestUri, final String contextPath, String mapping, final String expectedPathInfo, final String servletPath) throws IOException, ServletException { Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); HttpServletRequest request = createMock(HttpServletRequest.class); HttpServletResponse response = createMock(HttpServletResponse.class); expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) .andReturn(true); expect(injector.getBinding(Key.get(HttpServlet.class))) .andReturn(binding); final boolean[] run = new boolean[1]; //get an instance of this servlet expect(injector.getInstance(Key.get(HttpServlet.class))) .andReturn(new HttpServlet() { @Override protected void service(HttpServletRequest servletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { final String path = servletRequest.getPathInfo(); if (null == expectedPathInfo) { assertNull(String.format("expected [%s] but was [%s]", expectedPathInfo, path), path); } else { assertEquals(String.format("expected [%s] but was [%s]", expectedPathInfo, path), expectedPathInfo, path); } //assert memoizer //noinspection StringEquality assertSame("memo field did not work", path, servletRequest.getPathInfo()); run[0] = true; } }); expect(request.getRequestURI()) .andReturn(requestUri); expect(request.getServletPath()) .andReturn(servletPath) .anyTimes(); expect(request.getContextPath()) .andReturn(contextPath); expect(request.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(null); replay(injector, binding, request); ServletDefinition servletDefinition = new ServletDefinition(mapping, Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.REGEX, mapping), new HashMap(), null); servletDefinition.init(null, injector, Sets.newSetFromMap(Maps.newIdentityHashMap())); servletDefinition.doService(request, response); assertTrue("Servlet did not run!", run[0]); verify(injector, binding, request); } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/ContextPathTest.java0000644000175000017500000002427111542602000030140 0ustar drazzibdrazzib/** * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import static org.easymock.EasyMock.createControl; import static org.easymock.EasyMock.expect; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; import org.easymock.IMocksControl; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Scopes; import com.google.inject.name.Named; import com.google.inject.name.Names; /** Tests to make sure that servlets with a context path are handled right. */ public class ContextPathTest extends TestCase { @Inject @Named("foo") private TestServlet fooServlet; @Inject @Named("bar") private TestServlet barServlet; private IMocksControl globalControl; private Injector injector; private ServletContext servletContext; private FilterConfig filterConfig; private GuiceFilter guiceFilter; @Override public final void setUp() throws Exception { injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { bind(TestServlet.class).annotatedWith(Names.named("foo")) .to(TestServlet.class).in(Scopes.SINGLETON); bind(TestServlet.class).annotatedWith(Names.named("bar")) .to(TestServlet.class).in(Scopes.SINGLETON); serve("/foo/*").with(Key.get(TestServlet.class, Names.named("foo"))); serve("/bar/*").with(Key.get(TestServlet.class, Names.named("bar"))); // TODO: add a filter(..) call and validate it is correct } }); injector.injectMembers(this); assertNotNull(fooServlet); assertNotNull(barServlet); assertNotSame(fooServlet, barServlet); globalControl = createControl(); servletContext = globalControl.createMock(ServletContext.class); filterConfig = globalControl.createMock(FilterConfig.class); expect(servletContext.getAttribute(GuiceServletContextListener.INJECTOR_NAME)) .andReturn(injector).anyTimes(); expect(filterConfig.getServletContext()).andReturn(servletContext).anyTimes(); globalControl.replay(); guiceFilter = new GuiceFilter(); guiceFilter.init(filterConfig); } @Override public final void tearDown() { assertNotNull(fooServlet); assertNotNull(barServlet); fooServlet = null; barServlet = null; guiceFilter.destroy(); guiceFilter = null; injector = null; filterConfig = null; servletContext = null; globalControl.verify(); } public void testSimple() throws Exception { IMocksControl testControl = createControl(); TestFilterChain testFilterChain = new TestFilterChain(); HttpServletRequest req = testControl.createMock(HttpServletRequest.class); HttpServletResponse res = testControl.createMock(HttpServletResponse.class); expect(req.getMethod()).andReturn("GET").anyTimes(); expect(req.getRequestURI()).andReturn("/bar/foo").anyTimes(); expect(req.getServletPath()).andReturn("/bar/foo").anyTimes(); expect(req.getContextPath()).andReturn("").anyTimes(); testControl.replay(); guiceFilter.doFilter(req, res, testFilterChain); assertFalse(testFilterChain.isTriggered()); assertFalse(fooServlet.isTriggered()); assertTrue(barServlet.isTriggered()); testControl.verify(); } // // each of the following "runTest" calls takes three path parameters: // // The value of "getRequestURI()" // The value of "getServletPath()" // The value of "getContextPath()" // // these values have been captured using a filter in Apache Tomcat 6.0.32 // and are used for real-world values that a servlet container would send into // the GuiceFilter. // // the remaining three booleans are: // // True if the request gets passed down the filter chain // True if the request hits the "foo" servlet // True if the request hits the "bar" sevlet // // After adjusting the request URI for the web app deployment location, all // calls // should always produce the same result. // // ROOT Web app, using Tomcat default servlet public void testRootDefault() throws Exception { // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*). runTest("/", "/", "", true, false, false); // fetching /bar/. Should hit the bar servlet runTest("/bar/", "/bar/", "", false, false, true); // fetching /foo/xxx. Should hit the foo servlet runTest("/foo/xxx", "/foo/xxx", "", false, true, false); // fetching /xxx. Should go up the chain runTest("/xxx", "/xxx", "", true, false, false); } // ROOT Web app, using explicit backing servlet mounted at /* public void testRootExplicit() throws Exception { // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*). runTest("/", "", "", true, false, false); // fetching /bar/. Should hit the bar servlet runTest("/bar/", "", "", false, false, true); // fetching /foo/xxx. Should hit the foo servlet runTest("/foo/xxx", "", "", false, true, false); // fetching /xxx. Should go up the chain runTest("/xxx", "", "", true, false, false); } // ROOT Web app, using two backing servlets, mounted at /bar/* and /foo/* public void testRootSpecific() throws Exception { // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*). runTest("/", "/", "", true, false, false); // fetching /bar/. Should hit the bar servlet runTest("/bar/", "/bar", "", false, false, true); // fetching /foo/xxx. Should hit the foo servlet runTest("/foo/xxx", "/foo", "", false, true, false); // fetching /xxx. Should go up the chain runTest("/xxx", "/xxx", "", true, false, false); } // Web app located at /webtest, using Tomcat default servlet public void testWebtestDefault() throws Exception { // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*). runTest("/webtest/", "/", "/webtest", true, false, false); // fetching /bar/. Should hit the bar servlet runTest("/webtest/bar/", "/bar/", "/webtest", false, false, true); // fetching /foo/xxx. Should hit the foo servlet runTest("/webtest/foo/xxx", "/foo/xxx", "/webtest", false, true, false); // fetching /xxx. Should go up the chain runTest("/webtest/xxx", "/xxx", "/webtest", true, false, false); } // Web app located at /webtest, using explicit backing servlet mounted at /* public void testWebtestExplicit() throws Exception { // fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*). runTest("/webtest/", "", "/webtest", true, false, false); // fetching /bar/. Should hit the bar servlet runTest("/webtest/bar/", "", "/webtest", false, false, true); // fetching /foo/xxx. Should hit the foo servlet runTest("/webtest/foo/xxx", "", "/webtest", false, true, false); // fetching /xxx. Should go up the chain runTest("/webtest/xxx", "", "/webtest", true, false, false); } // Web app located at /webtest, using two backing servlets, mounted at /bar/* // and /foo/* public void testWebtestSpecific() throws Exception { // fetching /. Should go up the filter chain (only mappings on /foo/* and // /bar/*). runTest("/webtest/", "/", "/webtest", true, false, false); // fetching /bar/. Should hit the bar servlet runTest("/webtest/bar/", "/bar", "/webtest", false, false, true); // fetching /foo/xxx. Should hit the foo servlet runTest("/webtest/foo/xxx", "/foo", "/webtest", false, true, false); // fetching /xxx. Should go up the chain runTest("/webtest/xxx", "/xxx", "/webtest", true, false, false); } private void runTest(final String requestURI, final String servletPath, final String contextPath, final boolean filterResult, final boolean fooResult, final boolean barResult) throws Exception { IMocksControl testControl = createControl(); barServlet.clear(); fooServlet.clear(); TestFilterChain testFilterChain = new TestFilterChain(); HttpServletRequest req = testControl.createMock(HttpServletRequest.class); HttpServletResponse res = testControl.createMock(HttpServletResponse.class); expect(req.getMethod()).andReturn("GET").anyTimes(); expect(req.getRequestURI()).andReturn(requestURI).anyTimes(); expect(req.getServletPath()).andReturn(servletPath).anyTimes(); expect(req.getContextPath()).andReturn(contextPath).anyTimes(); testControl.replay(); guiceFilter.doFilter(req, res, testFilterChain); assertEquals(filterResult, testFilterChain.isTriggered()); assertEquals(fooResult, fooServlet.isTriggered()); assertEquals(barResult, barServlet.isTriggered()); testControl.verify(); } public static class TestServlet extends HttpServlet { private boolean triggered = false; @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) { triggered = true; } public boolean isTriggered() { return triggered; } public void clear() { triggered = false; } } public static class TestFilterChain implements FilterChain { private boolean triggered = false; public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { triggered = true; } public boolean isTriggered() { return triggered; } public void clear() { triggered = false; } } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/MultipleServletInjectorsTest.java0000644000175000017500000000725111434007752032734 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Injector; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.http.HttpServlet; import junit.framework.TestCase; import static com.google.inject.servlet.GuiceServletContextListener.INJECTOR_NAME; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.isA; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; /** * This gorgeous test asserts that multiple servlet pipelines can * run in the SAME JVM. booya. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class MultipleServletInjectorsTest extends TestCase { private Injector injectorOne; private Injector injectorTwo; public final void testTwoInjectors() { ServletContext fakeContextOne = createMock(ServletContext.class); ServletContext fakeContextTwo = createMock(ServletContext.class); fakeContextOne.setAttribute(eq(INJECTOR_NAME), isA(Injector.class)); expectLastCall().once(); fakeContextTwo.setAttribute(eq(INJECTOR_NAME), isA(Injector.class)); expectLastCall().once(); replay(fakeContextOne); // Simulate the start of a servlet container. new GuiceServletContextListener() { @Override protected Injector getInjector() { // Cache this injector in the test for later testing... return injectorOne = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { // This creates a ManagedFilterPipeline internally... serve("/*").with(DummyServlet.class); } }); } }.contextInitialized(new ServletContextEvent(fakeContextOne)); ServletContext contextOne = injectorOne.getInstance(ServletContext.class); assertNotNull(contextOne); // Now simulate a second injector with a slightly different config. replay(fakeContextTwo); new GuiceServletContextListener() { @Override protected Injector getInjector() { return injectorTwo = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { // This creates a ManagedFilterPipeline internally... filter("/8").through(DummyFilterImpl.class); serve("/*").with(HttpServlet.class); } }); } }.contextInitialized(new ServletContextEvent(fakeContextTwo)); ServletContext contextTwo = injectorTwo.getInstance(ServletContext.class); // Make sure they are different. assertNotNull(contextTwo); assertNotSame(contextOne, contextTwo); // Make sure they are as expected assertSame(fakeContextOne, contextOne); assertSame(fakeContextTwo, contextTwo); // Make sure they are consistent. assertSame(contextOne, injectorOne.getInstance(ServletContext.class)); assertSame(contextTwo, injectorTwo.getInstance(ServletContext.class)); verify(fakeContextOne, fakeContextTwo); } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/FilterPipelineTest.java0000644000175000017500000000733611542576630030640 0ustar drazzibdrazzibpackage com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Key; import com.google.inject.Singleton; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.isA; import static org.easymock.EasyMock.isNull; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import junit.framework.TestCase; /** * This is a basic whitebox test that verifies the glue between * GuiceFilter and ManagedFilterPipeline is working. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class FilterPipelineTest extends TestCase { @Override public final void setUp() { GuiceFilter.reset(); Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filter("/*").through(TestFilter.class); filter("*.html").through(TestFilter.class); filter("/*").through(Key.get(TestFilter.class)); filter("*.jsp").through(Key.get(TestFilter.class)); // These filters should never fire filter("/index/*").through(Key.get(NeverFilter.class)); filter("/public/login/*").through(Key.get(NeverFilter.class)); } }); } @Override public final void tearDown() { GuiceFilter.reset(); } public final void testDispatchThruGuiceFilter() throws ServletException, IOException { //create mocks FilterConfig filterConfig = createMock(FilterConfig.class); ServletContext servletContext = createMock(ServletContext.class); HttpServletRequest request = createMock(HttpServletRequest.class); FilterChain proceedingFilterChain = createMock(FilterChain.class); //begin mock script *** expect(filterConfig.getServletContext()) .andReturn(servletContext) .once(); expect(request.getRequestURI()) .andReturn("/public/login.jsp") .anyTimes(); expect(request.getContextPath()) .andReturn("") .anyTimes(); //at the end, proceed down webapp's normal filter chain proceedingFilterChain.doFilter(isA(HttpServletRequest.class), (ServletResponse) isNull()); expectLastCall().once(); //run mock script *** replay(filterConfig, servletContext, request, proceedingFilterChain); final GuiceFilter webFilter = new GuiceFilter(); webFilter.init(filterConfig); webFilter.doFilter(request, null, proceedingFilterChain); webFilter.destroy(); //assert expectations verify(filterConfig, servletContext, request, proceedingFilterChain); } @Singleton public static class TestFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } public void destroy() { } } @Singleton public static class NeverFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { fail("This filter should never have fired"); } public void destroy() { } } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/ServletDefinitionTest.java0000644000175000017500000000721711434212566031353 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Binding; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.spi.BindingScopingVisitor; import com.google.inject.internal.util.Maps; import com.google.inject.internal.util.Sets; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import junit.framework.TestCase; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.verify; /** * Basic unit test for lifecycle of a ServletDefinition (wrapper). * * @author Dhanji R. Prasanna (dhanji@gmail com) */ public class ServletDefinitionTest extends TestCase { public final void testServletInitAndConfig() throws ServletException { Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) .andReturn(true); expect(injector.getBinding(Key.get(HttpServlet.class))) .andReturn(binding); final HttpServlet mockServlet = new HttpServlet() { }; expect(injector.getInstance(Key.get(HttpServlet.class))) .andReturn(mockServlet) .anyTimes(); replay(injector, binding); //some init params //noinspection SSBasedInspection final Map initParams = new HashMap() { { put("ahsd", "asdas24dok"); put("ahssd", "asdasd124ok"); put("ahfsasd", "asda124sdok"); put("ahsasgd", "a124sdasdok"); put("ahsd124124", "as124124124dasdok"); } }; String pattern = "/*"; final ServletDefinition servletDefinition = new ServletDefinition(pattern, Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern), initParams, null); ServletContext servletContext = createMock(ServletContext.class); final String contextName = "thing__!@@44__SRV" + getClass(); expect(servletContext.getServletContextName()) .andReturn(contextName); replay(servletContext); servletDefinition.init(servletContext, injector, Sets.newSetFromMap(Maps.newIdentityHashMap())); assertNotNull(mockServlet.getServletContext()); assertEquals(contextName, mockServlet.getServletContext().getServletContextName()); assertEquals(Key.get(HttpServlet.class).toString(), mockServlet.getServletName()); final ServletConfig servletConfig = mockServlet.getServletConfig(); final Enumeration names = servletConfig.getInitParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); assertTrue(initParams.containsKey(name)); assertEquals(initParams.get(name), servletConfig.getInitParameter(name)); } verify(injector, binding, servletContext); } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/FilterDefinitionTest.java0000644000175000017500000002002611542576630031152 0ustar drazzibdrazzibpackage com.google.inject.servlet; import com.google.inject.Binding; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.internal.util.Maps; import com.google.inject.internal.util.Sets; import com.google.inject.spi.BindingScopingVisitor; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import junit.framework.TestCase; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; /** * Tests the lifecycle of the encapsulated {@link FilterDefinition} class. * * @author Dhanji R. Prasanna (dhanji@gmail com) */ public class FilterDefinitionTest extends TestCase { public final void testFilterInitAndConfig() throws ServletException { Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); final MockFilter mockFilter = new MockFilter(); expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) .andReturn(true); expect(injector.getBinding(Key.get(Filter.class))) .andReturn(binding); expect(injector.getInstance(Key.get(Filter.class))) .andReturn(mockFilter) .anyTimes(); replay(binding, injector); //some init params //noinspection SSBasedInspection final Map initParams = new HashMap() {{ put("ahsd", "asdas24dok"); put("ahssd", "asdasd124ok"); put("ahfsasd", "asda124sdok"); put("ahsasgd", "a124sdasdok"); put("ahsd124124", "as124124124dasdok"); }}; ServletContext servletContext = createMock(ServletContext.class); final String contextName = "thing__!@@44"; expect(servletContext.getServletContextName()).andReturn(contextName); replay(servletContext); String pattern = "/*"; final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class), UriPatternType.get(UriPatternType.SERVLET, pattern), initParams, null); filterDef.init(servletContext, injector, Sets.newSetFromMap(Maps.newIdentityHashMap())); assertTrue(filterDef.getFilter() instanceof MockFilter); final FilterConfig filterConfig = mockFilter.getConfig(); assertTrue(null != filterConfig); assertTrue(contextName.equals(filterConfig.getServletContext().getServletContextName())); assertTrue(Key.get(Filter.class).toString().equals(filterConfig.getFilterName())); final Enumeration names = filterConfig.getInitParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); assertTrue(initParams.containsKey(name)); assertTrue(initParams.get(name).equals(filterConfig.getInitParameter(name))); } verify(binding, injector, servletContext); } public final void testFilterCreateDispatchDestroy() throws ServletException, IOException { Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); HttpServletRequest request = createMock(HttpServletRequest.class); final MockFilter mockFilter = new MockFilter(); expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) .andReturn(true); expect(injector.getBinding(Key.get(Filter.class))) .andReturn(binding); expect(injector.getInstance(Key.get(Filter.class))) .andReturn(mockFilter) .anyTimes(); expect(request.getRequestURI()).andReturn("/index.html"); expect(request.getContextPath()) .andReturn("") .anyTimes(); replay(injector, binding, request); String pattern = "/*"; final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class), UriPatternType.get(UriPatternType.SERVLET, pattern), new HashMap(), null); //should fire on mockfilter now filterDef.init(createMock(ServletContext.class), injector, Sets.newSetFromMap(Maps.newIdentityHashMap())); assertTrue(filterDef.getFilter() instanceof MockFilter); assertTrue("Init did not fire", mockFilter.isInit()); final boolean proceed[] = new boolean[1]; filterDef.doFilter(request, null, new FilterChainInvocation(null, null, null) { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { proceed[0] = true; } }); assertTrue("Filter did not proceed down chain", proceed[0]); filterDef.destroy(Sets.newSetFromMap(Maps.newIdentityHashMap())); assertTrue("Destroy did not fire", mockFilter.isDestroy()); verify(injector, request); } public final void testFilterCreateDispatchDestroySupressChain() throws ServletException, IOException { Injector injector = createMock(Injector.class); Binding binding = createMock(Binding.class); HttpServletRequest request = createMock(HttpServletRequest.class); final MockFilter mockFilter = new MockFilter() { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { setRun(true); //suppress rest of chain... } }; expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) .andReturn(true); expect(injector.getBinding(Key.get(Filter.class))) .andReturn(binding); expect(injector.getInstance(Key.get(Filter.class))) .andReturn(mockFilter) .anyTimes(); expect(request.getRequestURI()).andReturn("/index.html"); expect(request.getContextPath()) .andReturn("") .anyTimes(); replay(injector, binding, request); String pattern = "/*"; final FilterDefinition filterDef = new FilterDefinition(pattern, Key.get(Filter.class), UriPatternType.get(UriPatternType.SERVLET, pattern), new HashMap(), null); //should fire on mockfilter now filterDef.init(createMock(ServletContext.class), injector, Sets.newSetFromMap(Maps.newIdentityHashMap())); assertTrue(filterDef.getFilter() instanceof MockFilter); assertTrue("init did not fire", mockFilter.isInit()); final boolean proceed[] = new boolean[1]; filterDef.doFilter(request, null, new FilterChainInvocation(null, null, null) { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { proceed[0] = true; } }); assertTrue("filter did not suppress chain", !proceed[0]); filterDef.destroy(Sets.newSetFromMap(Maps.newIdentityHashMap())); assertTrue("destroy did not fire", mockFilter.isDestroy()); verify(injector, request); } private static class MockFilter implements Filter { private boolean init; private boolean destroy; private boolean run; private FilterConfig config; public void init(FilterConfig filterConfig) throws ServletException { init = true; this.config = filterConfig; } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { run = true; //proceed filterChain.doFilter(servletRequest, servletResponse); } protected void setRun(boolean run) { this.run = run; } public void destroy() { destroy = true; } public boolean isInit() { return init; } public boolean isDestroy() { return destroy; } public boolean isRun() { return run; } public FilterConfig getConfig() { return config; } } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/InvalidScopeBindingTest.java0000644000175000017500000000526211434007752031566 0ustar drazzibdrazzibpackage com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Singleton; import com.google.inject.Scopes; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import junit.framework.TestCase; import static org.easymock.EasyMock.createMock; /** * Ensures that an error is thrown if a Servlet or Filter is bound * under any scope other than singleton, explicitly. * * @author dhanji@gmail.com */ public class InvalidScopeBindingTest extends TestCase { @Override protected void tearDown() throws Exception { GuiceFilter.reset(); } public final void testServletInNonSingletonScopeThrowsServletException(){ GuiceFilter guiceFilter = new GuiceFilter(); Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { serve("/*").with(MyNonSingletonServlet.class); } }); ServletException se = null; try { guiceFilter.init(createMock(FilterConfig.class)); } catch (ServletException e) { se = e; } finally { assertNotNull("Servlet exception was not thrown with wrong scope binding", se); } } public final void testFilterInNonSingletonScopeThrowsServletException(){ GuiceFilter guiceFilter = new GuiceFilter(); Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filter("/*").through(MyNonSingletonFilter.class); } }); ServletException se = null; try { guiceFilter.init(createMock(FilterConfig.class)); } catch (ServletException e) { se = e; } finally { assertNotNull("Servlet exception was not thrown with wrong scope binding", se); } } public final void testHappyCaseFilter(){ GuiceFilter guiceFilter = new GuiceFilter(); Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { // Annotated scoping variant. filter("/*").through(MySingletonFilter.class); // Explicit scoping variant. bind(DummyFilterImpl.class).in(Scopes.SINGLETON); filter("/*").through(DummyFilterImpl.class); } }); ServletException se = null; try { guiceFilter.init(createMock(FilterConfig.class)); } catch (ServletException e) { se = e; } finally { assertNull("Servlet exception was thrown with correct scope binding", se); } } @RequestScoped public static class MyNonSingletonServlet extends HttpServlet { } @SessionScoped public static class MyNonSingletonFilter extends DummyFilterImpl { } @Singleton public static class MySingletonFilter extends DummyFilterImpl { } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/DummyFilterImpl.java0000644000175000017500000000257311434007752030140 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Used in unit tests to verify the EDSL. * * @author Dhanji R. Prasanna (dhanji@gmail com) */ public class DummyFilterImpl implements Filter { int num; public DummyFilterImpl() { } public DummyFilterImpl(int num) { this.num = num; } public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { } public void destroy() { } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/EdslTest.java0000644000175000017500000000727111501200660026570 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Singleton; import com.google.inject.Stage; import java.util.HashMap; import junit.framework.TestCase; /** * Sanity checks the EDSL and resultant bound module(s). * * @author Dhanji R. Prasanna (dhanji gmail com) */ public class EdslTest extends TestCase { public final void testExplicitBindingsWorksWithGuiceServlet() { Injector injector = Guice.createInjector( new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); } }, new ServletModule() { @Override protected void configureServlets() { bind(DummyServlet.class).in(Singleton.class); serve("/*").with(DummyServlet.class); } }); assertNotNull(injector.getInstance(DummyServlet.class)); } public final void testConfigureServlets() { //the various possible config calls-- Module webModule = new ServletModule() { @Override protected void configureServlets() { filter("/*").through(DummyFilterImpl.class); filter("*.html").through(DummyFilterImpl.class); filter("/*").through(Key.get(DummyFilterImpl.class)); filter("/*").through(new DummyFilterImpl()); filter("*.html").through(DummyFilterImpl.class, new HashMap()); filterRegex("/person/[0-9]*").through(DummyFilterImpl.class); filterRegex("/person/[0-9]*").through(DummyFilterImpl.class, new HashMap()); filterRegex("/person/[0-9]*").through(Key.get(DummyFilterImpl.class)); filterRegex("/person/[0-9]*").through(Key.get(DummyFilterImpl.class), new HashMap()); filterRegex("/person/[0-9]*").through(new DummyFilterImpl()); filterRegex("/person/[0-9]*").through(new DummyFilterImpl(), new HashMap()); serve("/1/*").with(DummyServlet.class); serve("/2/*").with(Key.get(DummyServlet.class)); serve("/3/*").with(new DummyServlet()); serve("/4/*").with(DummyServlet.class, new HashMap()); serve("*.htm").with(Key.get(DummyServlet.class)); serve("*.html").with(Key.get(DummyServlet.class), new HashMap()); serveRegex("/person/[0-8]*").with(DummyServlet.class); serveRegex("/person/[0-9]*").with(DummyServlet.class, new HashMap()); serveRegex("/person/[0-6]*").with(Key.get(DummyServlet.class)); serveRegex("/person/[0-9]/2/*").with(Key.get(DummyServlet.class), new HashMap()); serveRegex("/person/[0-5]*").with(new DummyServlet()); serveRegex("/person/[0-9]/3/*").with(new DummyServlet(), new HashMap()); } }; //verify that it doesn't blow up! Guice.createInjector(Stage.TOOL, webModule); } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/ServletSpiVisitor.java0000644000175000017500000001201411467445306030533 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; import javax.servlet.Filter; import javax.servlet.ServletContext; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import junit.framework.AssertionFailedError; import com.google.inject.Binding; import com.google.inject.Injector; import com.google.inject.Stage; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Objects; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.DefaultBindingTargetVisitor; /** * A visitor for testing the servlet SPI extension. * * @author sameb@google.com (Sam Berlin) */ class ServletSpiVisitor extends DefaultBindingTargetVisitor implements ServletModuleTargetVisitor { int otherCount = 0; int currentCount = 0; List actual = Lists.newArrayList(); /* The set of classes that are allowed to be "other" bindings. */ Set allowedClasses; ServletSpiVisitor(boolean forInjector) { ImmutableSet.Builder builder = ImmutableSet.builder(); // always ignore these things... builder.add(ServletRequest.class, ServletResponse.class, ManagedFilterPipeline.class, ManagedServletPipeline.class, FilterPipeline.class, ServletContext.class, HttpServletRequest.class, Filter.class, HttpServletResponse.class, HttpSession.class, Map.class, HttpServlet.class); if(forInjector) { // only ignore these if this is for the live injector, any other time it'd be an error! builder.add(Injector.class, Stage.class, Logger.class); } this.allowedClasses = builder.build(); } public Integer visit(InstanceFilterBinding binding) { actual.add(new Params(binding, binding.getFilterInstance())); return currentCount++; } public Integer visit(InstanceServletBinding binding) { actual.add(new Params(binding, binding.getServletInstance())); return currentCount++; } public Integer visit(LinkedFilterBinding binding) { actual.add(new Params(binding, binding.getLinkedKey())); return currentCount++; } public Integer visit(LinkedServletBinding binding) { actual.add(new Params(binding, binding.getLinkedKey())); return currentCount++; } @Override protected Integer visitOther(Binding binding) { if(!allowedClasses.contains(binding.getKey().getTypeLiteral().getRawType())) { throw new AssertionFailedError("invalid other binding: " + binding); } otherCount++; return currentCount++; } static class Params { private final String pattern; private final Object keyOrInstance; private final Map params; private final UriPatternType patternType; Params(ServletModuleBinding binding, Object keyOrInstance) { this.pattern = binding.getPattern(); this.keyOrInstance = keyOrInstance; this.params = binding.getInitParams(); this.patternType = binding.getUriPatternType(); } Params(String pattern, Object keyOrInstance, Map params, UriPatternType patternType) { this.pattern = pattern; this.keyOrInstance = keyOrInstance; this.params = params; this.patternType = patternType; } @Override public boolean equals(Object obj) { if(obj instanceof Params) { Params o = (Params)obj; return Objects.equal(pattern, o.pattern) && Objects.equal(keyOrInstance, o.keyOrInstance) && Objects.equal(params, o.params) && Objects.equal(patternType, o.patternType); } else { return false; } } @Override public int hashCode() { return Objects.hashCode(pattern, keyOrInstance, params, patternType); } @Override public String toString() { return new ToStringBuilder(Params.class) .add("pattern", pattern) .add("keyOrInstance", keyOrInstance) .add("initParams", params) .add("patternType", patternType) .toString(); } } }guice-3.0/extensions/servlet/test/com/google/inject/servlet/ContinuingRequestIntegrationTest.java0000644000175000017500000001564011542576630033614 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableMap; import java.io.IOException; import java.util.List; import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; /** * Tests continuation of requests */ public class ContinuingRequestIntegrationTest extends TestCase { private static final String PARAM_VALUE = "there"; private static final String PARAM_NAME = "hi"; private final AtomicBoolean failed = new AtomicBoolean(false); private final AbstractExecutorService sameThreadExecutor = new AbstractExecutorService() { public void shutdown() { } public List shutdownNow() { return ImmutableList.of(); } public boolean isShutdown() { return true; } public boolean isTerminated() { return true; } public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { return true; } public void execute(Runnable command) { command.run(); } @Override public Future submit(Callable task) { try { task.call(); fail(); } catch (Exception e) { // Expected. assertTrue(e instanceof IllegalStateException); failed.set(true); } return null; } }; private ExecutorService executor; private Injector injector; @Override protected void tearDown() throws Exception { injector.getInstance(GuiceFilter.class).destroy(); } public final void testRequestContinuesInOtherThread() throws ServletException, IOException, InterruptedException { executor = Executors.newSingleThreadExecutor(); injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { serve("/*").with(ContinuingServlet.class); bind(ExecutorService.class).toInstance(executor); } }); FilterConfig filterConfig = createMock(FilterConfig.class); expect(filterConfig.getServletContext()).andReturn(createMock(ServletContext.class)); GuiceFilter guiceFilter = injector.getInstance(GuiceFilter.class); HttpServletRequest request = createMock(HttpServletRequest.class); expect(request.getRequestURI()).andReturn("/"); expect(request.getContextPath()) .andReturn("") .anyTimes(); expect(request.getMethod()).andReturn("GET"); FilterChain filterChain = createMock(FilterChain.class); expect(request.getParameter(PARAM_NAME)).andReturn(PARAM_VALUE); replay(request, filterConfig, filterChain); guiceFilter.init(filterConfig); guiceFilter.doFilter(request, null, filterChain); // join. executor.shutdown(); executor.awaitTermination(10, TimeUnit.SECONDS); assertEquals(PARAM_VALUE, injector.getInstance(OffRequestCallable.class).value); verify(request, filterConfig, filterChain); } public final void testRequestContinuationDiesInHttpRequestThread() throws ServletException, IOException, InterruptedException { executor = sameThreadExecutor; injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { serve("/*").with(ContinuingServlet.class); bind(ExecutorService.class).toInstance(executor); bind(SomeObject.class); } }); FilterConfig filterConfig = createMock(FilterConfig.class); expect(filterConfig.getServletContext()).andReturn(createMock(ServletContext.class)); GuiceFilter guiceFilter = injector.getInstance(GuiceFilter.class); HttpServletRequest request = createMock(HttpServletRequest.class); expect(request.getRequestURI()).andReturn("/"); expect(request.getContextPath()) .andReturn("") .anyTimes(); expect(request.getMethod()).andReturn("GET"); FilterChain filterChain = createMock(FilterChain.class); replay(request, filterConfig, filterChain); guiceFilter.init(filterConfig); guiceFilter.doFilter(request, null, filterChain); // join. executor.shutdown(); executor.awaitTermination(10, TimeUnit.SECONDS); assertTrue(failed.get()); assertFalse(PARAM_VALUE.equals(injector.getInstance(OffRequestCallable.class).value)); verify(request, filterConfig, filterChain); } @RequestScoped public static class SomeObject { } @Singleton public static class ContinuingServlet extends HttpServlet { @Inject OffRequestCallable callable; @Inject ExecutorService executorService; private SomeObject someObject; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { assertNull(someObject); // Seed with someobject. someObject = new SomeObject(); Callable task = ServletScopes.continueRequest(callable, ImmutableMap., Object>of(Key.get(SomeObject.class), someObject)); executorService.submit(task); } } @Singleton public static class OffRequestCallable implements Callable { @Inject Provider request; @Inject Provider response; @Inject Provider someObject; public String value; public String call() throws Exception { assertNull(response.get()); // Inside this request, we should always get the same instance. assertSame(someObject.get(), someObject.get()); return value = request.get().getParameter(PARAM_NAME); } } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/ServletDispatchIntegrationTest.java0000644000175000017500000002013311542576630033223 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; /** * Tests the FilterPipeline that dispatches to guice-managed servlets, * is a full integration test, with a real injector. * * @author Dhanji R. Prasanna (dhanji gmail com) */ public class ServletDispatchIntegrationTest extends TestCase { private static int inits, services, destroys, doFilters; @Override public void setUp() { inits = 0; services = 0; destroys = 0; doFilters = 0; GuiceFilter.reset(); } public final void testDispatchRequestToManagedPipelineServlets() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { serve("/*").with(TestServlet.class); // These servets should never fire... (ordering test) serve("*.html").with(NeverServlet.class); serve("/test/*").with(Key.get(NeverServlet.class)); serve("/index/*").with(Key.get(NeverServlet.class)); serve("*.jsp").with(Key.get(NeverServlet.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index.html") .times(1); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); //dispatch request replay(requestMock); pipeline.dispatch(requestMock, null, createMock(FilterChain.class)); pipeline.destroyPipeline(); verify(requestMock); assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: " + services + "; destroys: " + destroys, inits == 2 && services == 1 && destroys == 2); } public final void testDispatchRequestToManagedPipelineWithFilter() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filter("/*").through(TestFilter.class); serve("/*").with(TestServlet.class); // These servets should never fire... serve("*.html").with(NeverServlet.class); serve("/test/*").with(Key.get(NeverServlet.class)); serve("/index/*").with(Key.get(NeverServlet.class)); serve("*.jsp").with(Key.get(NeverServlet.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index.html") .times(2); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); //dispatch request replay(requestMock); pipeline.dispatch(requestMock, null, createMock(FilterChain.class)); pipeline.destroyPipeline(); verify(requestMock); assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: " + services + "; destroys: " + destroys + "; doFilters: " + doFilters, inits == 3 && services == 1 && destroys == 3 && doFilters == 1); } @Singleton public static class TestServlet extends HttpServlet { public void init(ServletConfig filterConfig) throws ServletException { inits++; } public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { services++; } public void destroy() { destroys++; } } @Singleton public static class NeverServlet extends HttpServlet { public void init(ServletConfig filterConfig) throws ServletException { inits++; } public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { assertTrue("NeverServlet was fired, when it should not have been.", false); } public void destroy() { destroys++; } } @Singleton public static class TestFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { inits++; } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { doFilters++; filterChain.doFilter(servletRequest, servletResponse); } public void destroy() { destroys++; } } @Singleton public static class ForwardingServlet extends HttpServlet { public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; request.getRequestDispatcher("/blah.jsp") .forward(servletRequest, servletResponse); } } @Singleton public static class ForwardedServlet extends HttpServlet { static int forwardedTo = 0; // Reset for test. public ForwardedServlet() { forwardedTo = 0; } public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; assertTrue((Boolean) request.getAttribute(REQUEST_DISPATCHER_REQUEST)); forwardedTo++; } } public void testForwardUsingRequestDispatcher() throws IOException, ServletException { Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { serve("/").with(ForwardingServlet.class); serve("/blah.jsp").with(ForwardedServlet.class); } }); final HttpServletRequest requestMock = createMock(HttpServletRequest.class); HttpServletResponse responseMock = createMock(HttpServletResponse.class); expect(requestMock.getRequestURI()) .andReturn("/") .anyTimes(); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true); expect(requestMock.getAttribute(REQUEST_DISPATCHER_REQUEST)).andReturn(true); requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST); expect(responseMock.isCommitted()).andReturn(false); responseMock.resetBuffer(); replay(requestMock, responseMock); new GuiceFilter() .doFilter(requestMock, responseMock, createMock(FilterChain.class)); assertEquals("Incorrect number of forwards", 1, ForwardedServlet.forwardedTo); verify(requestMock, responseMock); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootguice-3.0/extensions/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.javaguice-3.0/extensions/servlet/test/com/google/inject/servlet/VarargsFilterDispatchIntegrationTest.jav0000644000175000017500000001267411542576630034224 0ustar drazzibdrazzibpackage com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import junit.framework.TestCase; /** * * This tests that filter stage of the pipeline dispatches * correctly to guice-managed filters. * * WARNING(dhanji): Non-parallelizable test =( * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class VarargsFilterDispatchIntegrationTest extends TestCase { private static int inits, doFilters, destroys; @Override public final void setUp() { inits = 0; doFilters = 0; destroys = 0; GuiceFilter.reset(); } public final void testDispatchRequestToManagedPipeline() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { // This is actually a double match for "/*" filter("/*", "*.html", "/*").through(Key.get(TestFilter.class)); // These filters should never fire filter("/index/*").through(Key.get(TestFilter.class)); filter("*.jsp").through(Key.get(TestFilter.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index.html") .anyTimes(); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); //dispatch request replay(requestMock); pipeline.dispatch(requestMock, null, createMock(FilterChain.class)); pipeline.destroyPipeline(); verify(requestMock); assertTrue("lifecycle states did not" + " fire correct number of times-- inits: " + inits + "; dos: " + doFilters + "; destroys: " + destroys, inits == 1 && doFilters == 3 && destroys == 1); } public final void testDispatchThatNoFiltersFire() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filter("/public/*", "*.html", "*.xml").through(Key.get(TestFilter.class)); // These filters should never fire filter("/index/*").through(Key.get(TestFilter.class)); filter("*.jsp").through(Key.get(TestFilter.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index.xhtml") .anyTimes(); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); //dispatch request replay(requestMock); pipeline.dispatch(requestMock, null, createMock(FilterChain.class)); pipeline.destroyPipeline(); verify(requestMock); assertTrue("lifecycle states did not " + "fire correct number of times-- inits: " + inits + "; dos: " + doFilters + "; destroys: " + destroys, inits == 1 && doFilters == 0 && destroys == 1); } public final void testDispatchFilterPipelineWithRegexMatching() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filterRegex("/[A-Za-z]*", "/index").through(TestFilter.class); //these filters should never fire filterRegex("\\w").through(Key.get(TestFilter.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index") .anyTimes(); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); //dispatch request replay(requestMock); pipeline.dispatch(requestMock, null, createMock(FilterChain.class)); pipeline.destroyPipeline(); verify(requestMock); assertTrue("lifecycle states did not fire " + "correct number of times-- inits: " + inits + "; dos: " + doFilters + "; destroys: " + destroys, inits == 1 && doFilters == 2 && destroys == 1); } @Singleton public static class TestFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { inits++; } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { doFilters++; filterChain.doFilter(servletRequest, servletResponse); } public void destroy() { destroys++; } } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/ServletModuleTest.java0000644000175000017500000000630311447667152030514 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.util.List; import junit.framework.TestCase; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.internal.util.Lists; import com.google.inject.spi.DefaultBindingTargetVisitor; import com.google.inject.spi.Elements; /** * Tests for ServletModule, to ensure it captures bindings correctly. * * @author sameb@google.com (Sam Berlin) */ public class ServletModuleTest extends TestCase { public void testServletModuleReuse() { Module module = new Module(); Elements.getElements(module); // use the module once (to, say, introspect bindings) Injector injector = Guice.createInjector(module); // use it again. Visitor visitor = new Visitor(); // Validate only a single servlet binding & a single filter binding exist. for(Binding binding : injector.getAllBindings().values()) { binding.acceptTargetVisitor(visitor); } assertEquals("wrong linked servlets: " + visitor.linkedServlets, 0, visitor.linkedServlets.size()); assertEquals("wrong linked filters: " + visitor.linkedFilters, 0, visitor.linkedFilters.size()); assertEquals("wrong instance servlets: " + visitor.instanceServlets, 1, visitor.instanceServlets.size()); assertEquals("wrong instance filters: " + visitor.instanceFilters, 1, visitor.instanceFilters.size()); } private static class Module extends ServletModule { @Override protected void configureServlets() { serve("/sam/*").with(new DummyServlet()); filter("/tara/*").through(new DummyFilterImpl()); } } private static class Visitor extends DefaultBindingTargetVisitor implements ServletModuleTargetVisitor { List linkedFilters = Lists.newArrayList(); List linkedServlets = Lists.newArrayList(); List instanceFilters = Lists.newArrayList(); List instanceServlets = Lists.newArrayList(); public Void visit(LinkedFilterBinding binding) { linkedFilters.add(binding); return null; } public Void visit(InstanceFilterBinding binding) { instanceFilters.add(binding); return null; } public Void visit(LinkedServletBinding binding) { linkedServlets.add(binding); return null; } public Void visit(InstanceServletBinding binding) { instanceServlets.add(binding); return null; } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootguice-3.0/extensions/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.javaguice-3.0/extensions/servlet/test/com/google/inject/servlet/ServletPipelineRequestDispatcherTest.jav0000644000175000017500000002434611434212566034251 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Binding; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Maps; import com.google.inject.internal.util.Sets; import com.google.inject.spi.BindingScopingVisitor; import com.google.inject.util.Providers; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.UUID; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; /** * Tests forwarding and inclusion (RequestDispatcher actions from the * servlet spec). * * @author Dhanji R. Prasanna (dhanji@gmail com) */ public class ServletPipelineRequestDispatcherTest extends TestCase { private static final Key HTTP_SERLVET_KEY = Key.get(HttpServlet.class); private static final String A_KEY = "thinglyDEgintly" + new Date() + UUID.randomUUID(); private static final String A_VALUE = ServletPipelineRequestDispatcherTest.class.toString() + new Date() + UUID.randomUUID(); public final void testIncludeManagedServlet() throws IOException, ServletException { String pattern = "blah.html"; final ServletDefinition servletDefinition = new ServletDefinition(pattern, Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern), new HashMap(), null); final Injector injector = createMock(Injector.class); final Binding binding = createMock(Binding.class); final HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getAttribute(A_KEY)) .andReturn(A_VALUE); requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true); requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST); final boolean[] run = new boolean[1]; final HttpServlet mockServlet = new HttpServlet() { protected void service(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException { run[0] = true; final Object o = request.getAttribute(A_KEY); assertEquals("Wrong attrib returned - " + o, A_VALUE, o); } }; expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) .andReturn(true); expect(injector.getBinding(Key.get(HttpServlet.class))) .andReturn(binding); expect(injector.getInstance(HTTP_SERLVET_KEY)) .andReturn(mockServlet); final Key servetDefsKey = Key .get(TypeLiteral.get(ServletDefinition.class)); Binding mockBinding = createMock(Binding.class); expect(injector.findBindingsByType(eq(servetDefsKey.getTypeLiteral()))) .andReturn(ImmutableList.>of(mockBinding)); Provider bindingProvider = Providers.of(servletDefinition); expect(mockBinding.getProvider()) .andReturn(bindingProvider); replay(injector, binding, requestMock, mockBinding); // Have to init the Servlet before we can dispatch to it. servletDefinition.init(null, injector, Sets.newSetFromMap(Maps.newIdentityHashMap())); final RequestDispatcher dispatcher = new ManagedServletPipeline( injector) .getRequestDispatcher(pattern); assertNotNull(dispatcher); dispatcher.include(requestMock, createMock(HttpServletResponse.class)); assertTrue("Include did not dispatch to our servlet!", run[0]); verify(injector, requestMock, mockBinding); } public final void testForwardToManagedServlet() throws IOException, ServletException { String pattern = "blah.html"; final ServletDefinition servletDefinition = new ServletDefinition(pattern, Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern), new HashMap(), null); final Injector injector = createMock(Injector.class); final Binding binding = createMock(Binding.class); final HttpServletRequest requestMock = createMock(HttpServletRequest.class); final HttpServletResponse mockResponse = createMock(HttpServletResponse.class); expect(requestMock.getAttribute(A_KEY)) .andReturn(A_VALUE); requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true); requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST); expect(mockResponse.isCommitted()) .andReturn(false); mockResponse.resetBuffer(); expectLastCall().once(); final List paths = new ArrayList(); final HttpServlet mockServlet = new HttpServlet() { protected void service(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException { paths.add(request.getRequestURI()); final Object o = request.getAttribute(A_KEY); assertEquals("Wrong attrib returned - " + o, A_VALUE, o); } }; expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) .andReturn(true); expect(injector.getBinding(Key.get(HttpServlet.class))) .andReturn(binding); expect(injector.getInstance(HTTP_SERLVET_KEY)) .andReturn(mockServlet); final Key servetDefsKey = Key .get(TypeLiteral.get(ServletDefinition.class)); Binding mockBinding = createMock(Binding.class); expect(injector.findBindingsByType(eq(servetDefsKey.getTypeLiteral()))) .andReturn(ImmutableList.>of(mockBinding)); Provider bindingProvider = Providers.of(servletDefinition); expect(mockBinding.getProvider()) .andReturn(bindingProvider); replay(injector, binding, requestMock, mockResponse, mockBinding); // Have to init the Servlet before we can dispatch to it. servletDefinition.init(null, injector, Sets.newSetFromMap(Maps.newIdentityHashMap())); final RequestDispatcher dispatcher = new ManagedServletPipeline(injector) .getRequestDispatcher(pattern); assertNotNull(dispatcher); dispatcher.forward(requestMock, mockResponse); assertTrue("Include did not dispatch to our servlet!", paths.contains(pattern)); verify(injector, requestMock, mockResponse, mockBinding); } public final void testForwardToManagedServletFailureOnCommittedBuffer() throws IOException, ServletException { IllegalStateException expected = null; try { forwardToManagedServletFailureOnCommittedBuffer(); } catch (IllegalStateException ise) { expected = ise; } finally { assertNotNull("Expected IllegalStateException was not thrown", expected); } } public final void forwardToManagedServletFailureOnCommittedBuffer() throws IOException, ServletException { String pattern = "blah.html"; final ServletDefinition servletDefinition = new ServletDefinition(pattern, Key.get(HttpServlet.class), UriPatternType.get(UriPatternType.SERVLET, pattern), new HashMap(), null); final Injector injector = createMock(Injector.class); final Binding binding = createMock(Binding.class); final HttpServletRequest mockRequest = createMock(HttpServletRequest.class); final HttpServletResponse mockResponse = createMock(HttpServletResponse.class); expect(mockResponse.isCommitted()) .andReturn(true); final HttpServlet mockServlet = new HttpServlet() { protected void service(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException { final Object o = request.getAttribute(A_KEY); assertEquals("Wrong attrib returned - " + o, A_VALUE, o); } }; expect(binding.acceptScopingVisitor((BindingScopingVisitor) anyObject())) .andReturn(true); expect(injector.getBinding(Key.get(HttpServlet.class))) .andReturn(binding); expect(injector.getInstance(Key.get(HttpServlet.class))) .andReturn(mockServlet); final Key servetDefsKey = Key .get(TypeLiteral.get(ServletDefinition.class)); Binding mockBinding = createMock(Binding.class); expect(injector.findBindingsByType(eq(servetDefsKey.getTypeLiteral()))) .andReturn(ImmutableList.>of(mockBinding)); Provider bindingProvider = Providers.of(servletDefinition); expect(mockBinding.getProvider()) .andReturn(bindingProvider); replay(injector, binding, mockRequest, mockResponse, mockBinding); // Have to init the Servlet before we can dispatch to it. servletDefinition.init(null, injector, Sets.newSetFromMap(Maps.newIdentityHashMap())); final RequestDispatcher dispatcher = new ManagedServletPipeline(injector) .getRequestDispatcher(pattern); assertNotNull(dispatcher); try { dispatcher.forward(mockRequest, mockResponse); } finally { verify(injector, mockRequest, mockResponse, mockBinding); } } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/ExtensionSpiTest.java0000644000175000017500000002570711467445262030361 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import static com.google.inject.servlet.UriPatternType.REGEX; import static com.google.inject.servlet.UriPatternType.SERVLET; import java.util.Iterator; import java.util.List; import junit.framework.TestCase; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.name.Names; import com.google.inject.servlet.ServletSpiVisitor.Params; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; /** * A very basic test that servletmodule works with bindings. * * @author sameb@google.com (Sam Berlin) */ public class ExtensionSpiTest extends TestCase { private DummyFilterImpl dummyFilter1 = new DummyFilterImpl(); private DummyFilterImpl dummyFilter2 = new DummyFilterImpl(); private DummyFilterImpl dummyFilter3 = new DummyFilterImpl(); private DummyFilterImpl dummyFilter4 = new DummyFilterImpl(); private DummyServlet dummyServlet1 = new DummyServlet(); private DummyServlet dummyServlet2 = new DummyServlet(); private DummyServlet dummyServlet3 = new DummyServlet(); private DummyServlet dummyServlet4 = new DummyServlet(); public final void testSpiOnElements() { ServletSpiVisitor visitor = new ServletSpiVisitor(false); int count = 0; for(Element element : Elements.getElements(new Module())) { if(element instanceof Binding) { assertEquals(count++, ((Binding)element).acceptTargetVisitor(visitor)); } } validateVisitor(visitor); } public final void testSpiOnInjector() { ServletSpiVisitor visitor = new ServletSpiVisitor(true); int count = 0; Injector injector = Guice.createInjector(new Module()); for(Binding binding : injector.getBindings().values()) { assertEquals(count++, binding.acceptTargetVisitor(visitor)); } validateVisitor(visitor); } private void validateVisitor(ServletSpiVisitor visitor) { assertEquals(48, visitor.currentCount - visitor.otherCount); // This is the expected param list, in order.. List expected = ImmutableList.of( new Params("/class", Key.get(DummyFilterImpl.class), ImmutableMap.of(), SERVLET), new Params("/class/2", Key.get(DummyFilterImpl.class), ImmutableMap.of(), SERVLET), new Params("/key", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), SERVLET), new Params("/key/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), SERVLET), new Params("/instance", dummyFilter1, ImmutableMap.of(), SERVLET), new Params("/instance/2", dummyFilter1, ImmutableMap.of(), SERVLET), new Params("/class/keyvalues", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), SERVLET), new Params("/class/keyvalues/2", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), SERVLET), new Params("/key/keyvalues", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET), new Params("/key/keyvalues/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET), new Params("/instance/keyvalues", dummyFilter2, ImmutableMap.of("key", "value"), SERVLET), new Params("/instance/keyvalues/2", dummyFilter2, ImmutableMap.of("key", "value"), SERVLET), new Params("/class[0-9]", Key.get(DummyFilterImpl.class), ImmutableMap.of(), REGEX), new Params("/class[0-9]/2", Key.get(DummyFilterImpl.class), ImmutableMap.of(), REGEX), new Params("/key[0-9]", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), REGEX), new Params("/key[0-9]/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of(), REGEX), new Params("/instance[0-9]", dummyFilter3, ImmutableMap.of(), REGEX), new Params("/instance[0-9]/2", dummyFilter3, ImmutableMap.of(), REGEX), new Params("/class[0-9]/keyvalues", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), REGEX), new Params("/class[0-9]/keyvalues/2", Key.get(DummyFilterImpl.class), ImmutableMap.of("key", "value"), REGEX), new Params("/key[0-9]/keyvalues", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX), new Params("/key[0-9]/keyvalues/2", Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX), new Params("/instance[0-9]/keyvalues", dummyFilter4, ImmutableMap.of("key", "value"), REGEX), new Params("/instance[0-9]/keyvalues/2", dummyFilter4, ImmutableMap.of("key", "value"), REGEX), new Params("/class", Key.get(DummyServlet.class), ImmutableMap.of(), SERVLET), new Params("/class/2", Key.get(DummyServlet.class), ImmutableMap.of(), SERVLET), new Params("/key", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), SERVLET), new Params("/key/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), SERVLET), new Params("/instance", dummyServlet1, ImmutableMap.of(), SERVLET), new Params("/instance/2", dummyServlet1, ImmutableMap.of(), SERVLET), new Params("/class/keyvalues", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), SERVLET), new Params("/class/keyvalues/2", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), SERVLET), new Params("/key/keyvalues", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET), new Params("/key/keyvalues/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), SERVLET), new Params("/instance/keyvalues", dummyServlet2, ImmutableMap.of("key", "value"), SERVLET), new Params("/instance/keyvalues/2", dummyServlet2, ImmutableMap.of("key", "value"), SERVLET), new Params("/class[0-9]", Key.get(DummyServlet.class), ImmutableMap.of(), REGEX), new Params("/class[0-9]/2", Key.get(DummyServlet.class), ImmutableMap.of(), REGEX), new Params("/key[0-9]", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), REGEX), new Params("/key[0-9]/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of(), REGEX), new Params("/instance[0-9]", dummyServlet3, ImmutableMap.of(), REGEX), new Params("/instance[0-9]/2", dummyServlet3, ImmutableMap.of(), REGEX), new Params("/class[0-9]/keyvalues", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), REGEX), new Params("/class[0-9]/keyvalues/2", Key.get(DummyServlet.class), ImmutableMap.of("key", "value"), REGEX), new Params("/key[0-9]/keyvalues", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX), new Params("/key[0-9]/keyvalues/2", Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value"), REGEX), new Params("/instance[0-9]/keyvalues", dummyServlet4, ImmutableMap.of("key", "value"), REGEX), new Params("/instance[0-9]/keyvalues/2", dummyServlet4, ImmutableMap.of("key", "value"), REGEX) ); assertEquals(expected.size(), visitor.actual.size()); Iterator actualIterator = visitor.actual.iterator(); int i = 0; for(Params param : expected) { assertEquals("wrong " + i++ + "th param", param, actualIterator.next()); } } private class Module extends ServletModule { @Override protected void configureServlets() { filter("/class", "/class/2").through(DummyFilterImpl.class); filter("/key", "/key/2").through( Key.get(DummyFilterImpl.class, Names.named("foo"))); filter("/instance", "/instance/2").through(dummyFilter1); filter("/class/keyvalues", "/class/keyvalues/2").through( DummyFilterImpl.class, ImmutableMap.of("key", "value")); filter("/key/keyvalues", "/key/keyvalues/2").through( Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value")); filter("/instance/keyvalues", "/instance/keyvalues/2").through( dummyFilter2, ImmutableMap.of("key", "value")); filterRegex("/class[0-9]", "/class[0-9]/2").through(DummyFilterImpl.class); filterRegex("/key[0-9]", "/key[0-9]/2").through( Key.get(DummyFilterImpl.class, Names.named("foo"))); filterRegex("/instance[0-9]", "/instance[0-9]/2").through(dummyFilter3); filterRegex("/class[0-9]/keyvalues", "/class[0-9]/keyvalues/2").through( DummyFilterImpl.class, ImmutableMap.of("key", "value")); filterRegex("/key[0-9]/keyvalues", "/key[0-9]/keyvalues/2").through( Key.get(DummyFilterImpl.class, Names.named("foo")), ImmutableMap.of("key", "value")); filterRegex("/instance[0-9]/keyvalues", "/instance[0-9]/keyvalues/2").through( dummyFilter4, ImmutableMap.of("key", "value")); serve("/class", "/class/2").with(DummyServlet.class); serve("/key", "/key/2").with( Key.get(DummyServlet.class, Names.named("foo"))); serve("/instance", "/instance/2").with(dummyServlet1); serve("/class/keyvalues", "/class/keyvalues/2").with( DummyServlet.class, ImmutableMap.of("key", "value")); serve("/key/keyvalues", "/key/keyvalues/2").with( Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value")); serve("/instance/keyvalues", "/instance/keyvalues/2").with( dummyServlet2, ImmutableMap.of("key", "value")); serveRegex("/class[0-9]", "/class[0-9]/2").with(DummyServlet.class); serveRegex("/key[0-9]", "/key[0-9]/2").with( Key.get(DummyServlet.class, Names.named("foo"))); serveRegex("/instance[0-9]", "/instance[0-9]/2").with(dummyServlet3); serveRegex("/class[0-9]/keyvalues", "/class[0-9]/keyvalues/2").with( DummyServlet.class, ImmutableMap.of("key", "value")); serveRegex("/key[0-9]/keyvalues", "/key[0-9]/keyvalues/2").with( Key.get(DummyServlet.class, Names.named("foo")), ImmutableMap.of("key", "value")); serveRegex("/instance[0-9]/keyvalues", "/instance[0-9]/keyvalues/2").with( dummyServlet4, ImmutableMap.of("key", "value")); } }; } guice-3.0/extensions/servlet/test/com/google/inject/servlet/MultiModuleDispatchIntegrationTest.java0000644000175000017500000000614111542576630034042 0ustar drazzibdrazzibpackage com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import junit.framework.TestCase; /** * * This tests that filter stage of the pipeline dispatches * correctly to guice-managed filters with multiple modules. * * WARNING(dhanji): Non-parallelizable test =( * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class MultiModuleDispatchIntegrationTest extends TestCase { private static int inits, doFilters, destroys; @Override public final void setUp() { inits = 0; doFilters = 0; destroys = 0; GuiceFilter.reset(); } public final void testDispatchRequestToManagedPipeline() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filter("/*").through(TestFilter.class); // These filters should never fire filter("*.jsp").through(Key.get(TestFilter.class)); } }, new ServletModule() { @Override protected void configureServlets() { filter("*.html").through(TestFilter.class); filter("/*").through(Key.get(TestFilter.class)); // These filters should never fire filter("/index/*").through(Key.get(TestFilter.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index.html") .anyTimes(); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); //dispatch request replay(requestMock); pipeline.dispatch(requestMock, null, createMock(FilterChain.class)); pipeline.destroyPipeline(); verify(requestMock); assertTrue("lifecycle states did not" + " fire correct number of times-- inits: " + inits + "; dos: " + doFilters + "; destroys: " + destroys, inits == 1 && doFilters == 3 && destroys == 1); } @Singleton public static class TestFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { inits++; } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { doFilters++; filterChain.doFilter(servletRequest, servletResponse); } public void destroy() { destroys++; } } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/ServletTest.java0000644000175000017500000002500311434007752027332 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.AbstractModule; import static com.google.inject.Asserts.reserialize; import com.google.inject.BindingAnnotation; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.internal.util.Maps; import static com.google.inject.servlet.ServletScopes.NullObject; import com.google.inject.util.Providers; import java.io.IOException; import java.io.Serializable; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Map; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import junit.framework.TestCase; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.isA; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; /** * @author crazybob@google.com (Bob Lee) */ public class ServletTest extends TestCase { private static final Key IN_REQUEST_KEY = Key.get(InRequest.class); private static final Key IN_REQUEST_NULL_KEY = Key.get(InRequest.class, Null.class); private static final Key IN_SESSION_KEY = Key.get(InSession.class); private static final Key IN_SESSION_NULL_KEY = Key.get(InSession.class, Null.class); @Override public void setUp() { //we need to clear the reference to the pipeline every test =( GuiceFilter.reset(); } public void testNewRequestObject() throws CreationException, IOException, ServletException { final Injector injector = createInjector(); GuiceFilter filter = new GuiceFilter(); final HttpServletRequest request = createMock(HttpServletRequest.class); String inRequestKey = IN_REQUEST_KEY.toString(); expect(request.getAttribute(inRequestKey)).andReturn(null); request.setAttribute(eq(inRequestKey), isA(InRequest.class)); String inRequestNullKey = IN_REQUEST_NULL_KEY.toString(); expect(request.getAttribute(inRequestNullKey)).andReturn(null); request.setAttribute(eq(inRequestNullKey), eq(NullObject.INSTANCE)); final boolean[] invoked = new boolean[1]; FilterChain filterChain = new FilterChain() { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { invoked[0] = true; // assertSame(request, servletRequest); assertNotNull(injector.getInstance(InRequest.class)); assertNull(injector.getInstance(IN_REQUEST_NULL_KEY)); } }; replay(request); filter.doFilter(request, null, filterChain); verify(request); assertTrue(invoked[0]); } public void testExistingRequestObject() throws CreationException, IOException, ServletException { final Injector injector = createInjector(); GuiceFilter filter = new GuiceFilter(); final HttpServletRequest request = createMock(HttpServletRequest.class); final InRequest inRequest = new InRequest(); String inRequestKey = IN_REQUEST_KEY.toString(); expect(request.getAttribute(inRequestKey)).andReturn(inRequest).times(2); String inRequestNullKey = IN_REQUEST_NULL_KEY.toString(); expect(request.getAttribute(inRequestNullKey)).andReturn(NullObject.INSTANCE).times(2); final boolean[] invoked = new boolean[1]; FilterChain filterChain = new FilterChain() { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { invoked[0] = true; assertSame(inRequest, injector.getInstance(InRequest.class)); assertSame(inRequest, injector.getInstance(InRequest.class)); assertNull(injector.getInstance(IN_REQUEST_NULL_KEY)); assertNull(injector.getInstance(IN_REQUEST_NULL_KEY)); } }; replay(request); filter.doFilter(request, null, filterChain); verify(request); assertTrue(invoked[0]); } public void testNewSessionObject() throws CreationException, IOException, ServletException { final Injector injector = createInjector(); GuiceFilter filter = new GuiceFilter(); final HttpServletRequest request = createMock(HttpServletRequest.class); final HttpSession session = createMock(HttpSession.class); String inSessionKey = IN_SESSION_KEY.toString(); String inSessionNullKey = IN_SESSION_NULL_KEY.toString(); expect(request.getSession()).andReturn(session).times(2); expect(session.getAttribute(inSessionKey)).andReturn(null); session.setAttribute(eq(inSessionKey), isA(InSession.class)); expect(session.getAttribute(inSessionNullKey)).andReturn(null); session.setAttribute(eq(inSessionNullKey), eq(NullObject.INSTANCE)); final boolean[] invoked = new boolean[1]; FilterChain filterChain = new FilterChain() { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { invoked[0] = true; // assertSame(request, servletRequest); assertNotNull(injector.getInstance(InSession.class)); assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); } }; replay(request, session); filter.doFilter(request, null, filterChain); verify(request, session); assertTrue(invoked[0]); } public void testExistingSessionObject() throws CreationException, IOException, ServletException { final Injector injector = createInjector(); GuiceFilter filter = new GuiceFilter(); final HttpServletRequest request = createMock(HttpServletRequest.class); final HttpSession session = createMock(HttpSession.class); String inSessionKey = IN_SESSION_KEY.toString(); String inSessionNullKey = IN_SESSION_NULL_KEY.toString(); final InSession inSession = new InSession(); expect(request.getSession()).andReturn(session).times(4); expect(session.getAttribute(inSessionKey)).andReturn(inSession).times(2); expect(session.getAttribute(inSessionNullKey)).andReturn(NullObject.INSTANCE).times(2); final boolean[] invoked = new boolean[1]; FilterChain filterChain = new FilterChain() { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { invoked[0] = true; // assertSame(request, servletRequest); assertSame(inSession, injector.getInstance(InSession.class)); assertSame(inSession, injector.getInstance(InSession.class)); assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); } }; replay(request, session); filter.doFilter(request, null, filterChain); verify(request, session); assertTrue(invoked[0]); } public void testHttpSessionIsSerializable() throws IOException, ClassNotFoundException, ServletException { final Injector injector = createInjector(); GuiceFilter filter = new GuiceFilter(); final HttpServletRequest request = createMock(HttpServletRequest.class); final HttpSession session = newFakeHttpSession(); String inSessionKey = IN_SESSION_KEY.toString(); String inSessionNullKey = IN_SESSION_NULL_KEY.toString(); expect(request.getSession()).andReturn(session).times(2); final boolean[] invoked = new boolean[1]; FilterChain filterChain = new FilterChain() { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { invoked[0] = true; assertNotNull(injector.getInstance(InSession.class)); assertNull(injector.getInstance(IN_SESSION_NULL_KEY)); } }; replay(request); filter.doFilter(request, null, filterChain); verify(request); assertTrue(invoked[0]); HttpSession deserializedSession = reserialize(session); assertTrue(deserializedSession.getAttribute(inSessionKey) instanceof InSession); assertEquals(NullObject.INSTANCE, deserializedSession.getAttribute(inSessionNullKey)); } private static class FakeHttpSessionHandler implements InvocationHandler, Serializable { final Map attributes = Maps.newHashMap(); public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if ("setAttribute".equals(name)) { attributes.put((String) args[0], args[1]); return null; } else if ("getAttribute".equals(name)) { return attributes.get(args[0]); } else { throw new UnsupportedOperationException(); } } } /** * Returns a fake, serializable HttpSession which stores attributes in a HashMap. */ private HttpSession newFakeHttpSession() { return (HttpSession) Proxy.newProxyInstance(HttpSession.class.getClassLoader(), new Class[] { HttpSession.class }, new FakeHttpSessionHandler()); } private Injector createInjector() throws CreationException { return Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new ServletModule()); bind(InSession.class); bind(IN_SESSION_NULL_KEY).toProvider(Providers.of(null)).in(SessionScoped.class); bind(InRequest.class); bind(IN_REQUEST_NULL_KEY).toProvider(Providers.of(null)).in(RequestScoped.class); } }); } @SessionScoped static class InSession implements Serializable {} @RequestScoped static class InRequest {} @BindingAnnotation @Retention(RUNTIME) @Target({PARAMETER, METHOD, FIELD}) @interface Null {} } guice-3.0/extensions/servlet/test/com/google/inject/servlet/FilterDispatchIntegrationTest.java0000644000175000017500000001745011542576630033034 0ustar drazzibdrazzibpackage com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; import org.easymock.EasyMock; import org.easymock.IMocksControl; import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; /** * * This tests that filter stage of the pipeline dispatches * correctly to guice-managed filters. * * WARNING(dhanji): Non-parallelizable test =( * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class FilterDispatchIntegrationTest extends TestCase { private static int inits, doFilters, destroys; private IMocksControl control; @Override public final void setUp() { inits = 0; doFilters = 0; destroys = 0; control = EasyMock.createControl(); GuiceFilter.reset(); } public final void testDispatchRequestToManagedPipeline() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filter("/*").through(TestFilter.class); filter("*.html").through(TestFilter.class); filter("/*").through(Key.get(TestFilter.class)); // These filters should never fire filter("/index/*").through(Key.get(TestFilter.class)); filter("*.jsp").through(Key.get(TestFilter.class)); // Bind a servlet serve("*.html").with(TestServlet.class); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); // create ourselves a mock request with test URI HttpServletRequest requestMock = control.createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index.html") .anyTimes(); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); requestMock.setAttribute(REQUEST_DISPATCHER_REQUEST, true); requestMock.removeAttribute(REQUEST_DISPATCHER_REQUEST); HttpServletResponse responseMock = control.createMock(HttpServletResponse.class); expect(responseMock.isCommitted()) .andReturn(false) .anyTimes(); responseMock.resetBuffer(); expectLastCall().anyTimes(); FilterChain filterChain = control.createMock(FilterChain.class); //dispatch request control.replay(); pipeline.dispatch(requestMock, responseMock, filterChain); pipeline.destroyPipeline(); control.verify(); TestServlet servlet = injector.getInstance(TestServlet.class); assertEquals(2, servlet.processedUris.size()); assertTrue(servlet.processedUris.contains("/index.html")); assertTrue(servlet.processedUris.contains(TestServlet.FORWARD_TO)); assertTrue("lifecycle states did not" + " fire correct number of times-- inits: " + inits + "; dos: " + doFilters + "; destroys: " + destroys, inits == 1 && doFilters == 3 && destroys == 1); } public final void testDispatchThatNoFiltersFire() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filter("/public/*").through(TestFilter.class); filter("*.html").through(TestFilter.class); filter("*.xml").through(Key.get(TestFilter.class)); // These filters should never fire filter("/index/*").through(Key.get(TestFilter.class)); filter("*.jsp").through(Key.get(TestFilter.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = control.createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index.xhtml") .anyTimes(); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); //dispatch request FilterChain filterChain = control.createMock(FilterChain.class); filterChain.doFilter(requestMock, null); control.replay(); pipeline.dispatch(requestMock, null, filterChain); pipeline.destroyPipeline(); control.verify(); assertTrue("lifecycle states did not " + "fire correct number of times-- inits: " + inits + "; dos: " + doFilters + "; destroys: " + destroys, inits == 1 && doFilters == 0 && destroys == 1); } public final void testDispatchFilterPipelineWithRegexMatching() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filterRegex("/[A-Za-z]*").through(TestFilter.class); filterRegex("/index").through(TestFilter.class); //these filters should never fire filterRegex("\\w").through(Key.get(TestFilter.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = control.createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index") .anyTimes(); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); // dispatch request FilterChain filterChain = control.createMock(FilterChain.class); filterChain.doFilter(requestMock, null); control.replay(); pipeline.dispatch(requestMock, null, filterChain); pipeline.destroyPipeline(); control.verify(); assertTrue("lifecycle states did not fire " + "correct number of times-- inits: " + inits + "; dos: " + doFilters + "; destroys: " + destroys, inits == 1 && doFilters == 2 && destroys == 1); } @Singleton public static class TestFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { inits++; } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { doFilters++; filterChain.doFilter(servletRequest, servletResponse); } public void destroy() { destroys++; } } @Singleton public static class TestServlet extends HttpServlet { public static final String FORWARD_FROM = "/index.html"; public static final String FORWARD_TO = "/forwarded.html"; public List processedUris = new ArrayList(); protected void service(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { String requestUri = httpServletRequest.getRequestURI(); processedUris.add(requestUri); // If the client is requesting /index.html then we forward to /forwarded.html if (FORWARD_FROM.equals(requestUri)) { httpServletRequest.getRequestDispatcher(FORWARD_TO) .forward(httpServletRequest, httpServletResponse); } } public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { service((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse); } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootguice-3.0/extensions/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.javaguice-3.0/extensions/servlet/test/com/google/inject/servlet/VarargsServletDispatchIntegrationTest.ja0000644000175000017500000001555511542576630034236 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Singleton; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import junit.framework.TestCase; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; /** * Tests the FilterPipeline that dispatches to guice-managed servlets, * is a full integration test, with a real injector. * * @author Dhanji R. Prasanna (dhanji gmail com) */ public class VarargsServletDispatchIntegrationTest extends TestCase { private static int inits, services, destroys, doFilters; @Override public void setUp() { inits = 0; services = 0; destroys = 0; doFilters = 0; GuiceFilter.reset(); } public final void testDispatchRequestToManagedPipelineServlets() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { serve("/*", "/index.html").with(TestServlet.class); // These servets should never fire... (ordering test) serve("*.html", "/o/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index.html") .times(1); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); //dispatch request replay(requestMock); pipeline.dispatch(requestMock, null, createMock(FilterChain.class)); pipeline.destroyPipeline(); verify(requestMock); assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: " + services + "; destroys: " + destroys, inits == 2 && services == 1 && destroys == 2); } public final void testVarargsSkipDispatchRequestToManagedPipelineServlets() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { serve("/notindex", "/&*", "/index.html").with(TestServlet.class); // These servets should never fire... (ordering test) serve("*.html", "/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index.html") .times(3); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); //dispatch request replay(requestMock); pipeline.dispatch(requestMock, null, createMock(FilterChain.class)); pipeline.destroyPipeline(); verify(requestMock); assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: " + services + "; destroys: " + destroys, inits == 2 && services == 1 && destroys == 2); } public final void testDispatchRequestToManagedPipelineWithFilter() throws ServletException, IOException { final Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { filter("/*").through(TestFilter.class); serve("/*").with(TestServlet.class); // These servets should never fire... serve("*.html", "/y/*", "/index/*", "*.jsp").with(Key.get(NeverServlet.class)); } }); final FilterPipeline pipeline = injector.getInstance(FilterPipeline.class); pipeline.initPipeline(null); //create ourselves a mock request with test URI HttpServletRequest requestMock = createMock(HttpServletRequest.class); expect(requestMock.getRequestURI()) .andReturn("/index.html") .times(2); expect(requestMock.getContextPath()) .andReturn("") .anyTimes(); //dispatch request replay(requestMock); pipeline.dispatch(requestMock, null, createMock(FilterChain.class)); pipeline.destroyPipeline(); verify(requestMock); assertTrue("lifecycle states did not fire correct number of times-- inits: " + inits + "; dos: " + services + "; destroys: " + destroys, inits == 3 && services == 1 && destroys == 3 && doFilters == 1); } @Singleton public static class TestServlet extends HttpServlet { public void init(ServletConfig filterConfig) throws ServletException { inits++; } public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { services++; } public void destroy() { destroys++; } } @Singleton public static class NeverServlet extends HttpServlet { public void init(ServletConfig filterConfig) throws ServletException { inits++; } public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { assertTrue("NeverServlet was fired, when it should not have been.", false); } public void destroy() { destroys++; } } @Singleton public static class TestFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { inits++; } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { doFilters++; filterChain.doFilter(servletRequest, servletResponse); } public void destroy() { destroys++; } } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/DummyServlet.java0000644000175000017500000000155011434007752027507 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Singleton; import javax.servlet.http.HttpServlet; /** * Used in unit tests to verify the EDSL. * * @author Dhanji R. Prasanna (dhanji@gmail com) */ @Singleton public class DummyServlet extends HttpServlet { } guice-3.0/extensions/servlet/test/com/google/inject/servlet/ScopeRequestIntegrationTest.java0000644000175000017500000001375011475262334032546 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.OutOfScopeException; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.Singleton; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.Maps; import com.google.inject.name.Named; import com.google.inject.name.Names; import java.io.IOException; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import junit.framework.TestCase; /** * Tests continuation of requests */ public class ScopeRequestIntegrationTest extends TestCase { private static final String A_VALUE = "thereaoskdao"; private static final String A_DIFFERENT_VALUE = "hiaoskd"; private static final String SHOULDNEVERBESEEN = "Shouldneverbeseen!"; public final void testNonHttpRequestScopedCallable() throws ServletException, IOException, InterruptedException, ExecutionException { ExecutorService executor = Executors.newSingleThreadExecutor(); // We use servlet module here because we want to test that @RequestScoped // behaves properly with the non-HTTP request scope logic. Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN); bind(SomeObject.class).in(RequestScoped.class); } }); SomeObject someObject = new SomeObject(A_VALUE); OffRequestCallable offRequestCallable = injector.getInstance(OffRequestCallable.class); executor.submit(ServletScopes.scopeRequest(offRequestCallable, ImmutableMap., Object>of(Key.get(SomeObject.class), someObject))).get(); assertSame(injector.getInstance(OffRequestCallable.class), offRequestCallable); // Make sure the value was passed on. assertEquals(someObject.value, offRequestCallable.value); assertFalse(SHOULDNEVERBESEEN.equals(someObject.value)); // Now create a new request and assert that the scopes don't cross. someObject = new SomeObject(A_DIFFERENT_VALUE); executor.submit(ServletScopes.scopeRequest(offRequestCallable, ImmutableMap., Object>of(Key.get(SomeObject.class), someObject))).get(); assertSame(injector.getInstance(OffRequestCallable.class), offRequestCallable); // Make sure the value was passed on. assertEquals(someObject.value, offRequestCallable.value); assertFalse(SHOULDNEVERBESEEN.equals(someObject.value)); executor.shutdown(); executor.awaitTermination(2, TimeUnit.SECONDS); } public final void testWrongValueClasses() throws Exception { Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN); bind(SomeObject.class).in(RequestScoped.class); } }); OffRequestCallable offRequestCallable = injector.getInstance(OffRequestCallable.class); try { ServletScopes.scopeRequest(offRequestCallable, ImmutableMap., Object>of(Key.get(SomeObject.class), "Boo!")); fail(); } catch(IllegalArgumentException iae) { assertEquals("Value[Boo!] of type[java.lang.String] is not compatible with key[" + Key.get(SomeObject.class) + "]", iae.getMessage()); } } public final void testNullReplacement() throws Exception { Injector injector = Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { bindConstant().annotatedWith(Names.named(SomeObject.INVALID)).to(SHOULDNEVERBESEEN); bind(SomeObject.class).in(RequestScoped.class); } }); Callable callable = injector.getInstance(Caller.class); try { assertNotNull(callable.call()); fail(); } catch(ProvisionException pe) { assertTrue(pe.getCause() instanceof OutOfScopeException); } // Validate that an actual null entry in the map results in a null injected object. Map, Object> map = Maps.newHashMap(); map.put(Key.get(SomeObject.class), null); callable = ServletScopes.scopeRequest(injector.getInstance(Caller.class), map); assertNull(callable.call()); } @RequestScoped public static class SomeObject { private static final String INVALID = "invalid"; @Inject public SomeObject(@Named(INVALID) String value) { this.value = value; } private final String value; } @Singleton public static class OffRequestCallable implements Callable { @Inject Provider someObject; public String value; public String call() throws Exception { // Inside this request, we should always get the same instance. assertSame(someObject.get(), someObject.get()); value = someObject.get().value; assertFalse(SHOULDNEVERBESEEN.equals(value)); return value; } } private static class Caller implements Callable { @Inject Provider someObject; public SomeObject call() throws Exception { return someObject.get(); } } } guice-3.0/extensions/servlet/test/com/google/inject/servlet/AllTests.java0000644000175000017500000000352311447667050026613 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import junit.framework.Test; import junit.framework.TestSuite; /** * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class AllTests { public static Test suite() { TestSuite suite = new TestSuite(); // Filter tests. suite.addTestSuite(EdslTest.class); suite.addTestSuite(FilterDefinitionTest.class); suite.addTestSuite(FilterDispatchIntegrationTest.class); suite.addTestSuite(FilterPipelineTest.class); // Servlet + integration tests. suite.addTestSuite(ServletModuleTest.class); suite.addTestSuite(ServletTest.class); suite.addTestSuite(ServletDefinitionTest.class); suite.addTestSuite(ServletDefinitionPathsTest.class); suite.addTestSuite(ServletPipelineRequestDispatcherTest.class); suite.addTestSuite(ServletDispatchIntegrationTest.class); suite.addTestSuite(InvalidScopeBindingTest.class); // Varargs URL mapping tests. suite.addTestSuite(VarargsFilterDispatchIntegrationTest.class); suite.addTestSuite(VarargsServletDispatchIntegrationTest.class); // Multiple modules tests. suite.addTestSuite(MultiModuleDispatchIntegrationTest.class); // Extension SPI tests. suite.addTestSuite(ExtensionSpiTest.class); return suite; } } guice-3.0/extensions/servlet/src/0000755000175000017500000000000011434007750017017 5ustar drazzibdrazzibguice-3.0/extensions/servlet/src/com/0000755000175000017500000000000011434007750017575 5ustar drazzibdrazzibguice-3.0/extensions/servlet/src/com/google/0000755000175000017500000000000011434007750021051 5ustar drazzibdrazzibguice-3.0/extensions/servlet/src/com/google/inject/0000755000175000017500000000000011434007750022325 5ustar drazzibdrazzibguice-3.0/extensions/servlet/src/com/google/inject/servlet/0000755000175000017500000000000011467443002024011 5ustar drazzibdrazzibguice-3.0/extensions/servlet/src/com/google/inject/servlet/InstanceServletBindingImpl.java0000644000175000017500000000311711467443710032112 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.util.Map; import javax.servlet.http.HttpServlet; import com.google.inject.internal.util.ToStringBuilder; /** * Default implementation of InstanceServletBinding. * * @author sameb@google.com (Sam Berlin) */ class InstanceServletBindingImpl extends AbstractServletModuleBinding implements InstanceServletBinding { InstanceServletBindingImpl(Map initParams, String pattern, HttpServlet target, UriPatternMatcher patternMatcher) { super(initParams, pattern, target, patternMatcher); } public HttpServlet getServletInstance() { return getTarget(); } @Override public String toString() { return new ToStringBuilder(InstanceServletBinding.class) .add("pattern", getPattern()) .add("initParams", getInitParams()) .add("uriPatternType", getUriPatternType()) .add("servletInstance", getServletInstance()) .toString(); } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/package-info.java0000644000175000017500000000174511461123536027210 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Servlet API scopes, bindings and registration; this extension requires {@code * guice-servlet-3.0.jar}. * *

Apply {@link com.google.inject.servlet.GuiceFilter} to any servlets which will use the servlet * scopes. Install {@link com.google.inject.servlet.ServletModule} into your {@link * com.google.inject.Injector} to install everything at once. */ package com.google.inject.servlet;guice-3.0/extensions/servlet/src/com/google/inject/servlet/RequestScoped.java0000644000175000017500000000212311434007752027442 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.ScopeAnnotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Apply this to implementation classes when you want one instance per request. * * @author crazybob@google.com (Bob Lee) */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @ScopeAnnotation public @interface RequestScoped {} guice-3.0/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java0000644000175000017500000001054611434007752031153 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.AbstractModule; import com.google.inject.Provider; import com.google.inject.Provides; import com.google.inject.Singleton; import java.util.Map; import java.util.logging.Logger; import javax.servlet.ServletContext; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import static com.google.inject.servlet.ServletScopes.REQUEST; import static com.google.inject.servlet.ServletScopes.SESSION; /** * This is a left-factoring of all ServletModules installed in the system. * In other words, this module contains the bindings common to all ServletModules, * and is bound exactly once per injector. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ final class InternalServletModule extends AbstractModule { /** * Special Provider that tries to obtain an injected servlet context, specific * to the current injector, failing which, it falls back to the static singleton * instance that is available in the legacy Guice Servlet. */ @Singleton static class BackwardsCompatibleServletContextProvider implements Provider { private ServletContext injectedServletContext; // This setter is called by the GuiceServletContextListener void set(ServletContext injectedServletContext) { this.injectedServletContext = injectedServletContext; } public ServletContext get() { if (null != injectedServletContext) { return injectedServletContext; } Logger.getLogger(InternalServletModule.class.getName()) .warning("You are attempting to use a deprecated API (specifically," + " attempting to @Inject ServletContext inside an eagerly created" + " singleton. While we allow this for backwards compatibility, be" + " warned that this MAY have unexpected behavior if you have more" + " than one injector (with ServletModule) running in the same JVM." + " Please consult the Guice documentation at" + " http://code.google.com/p/google-guice/wiki/Servlets for more" + " information."); return GuiceFilter.getServletContext(); } } @Override protected void configure() { bindScope(RequestScoped.class, REQUEST); bindScope(SessionScoped.class, SESSION); bind(ServletRequest.class).to(HttpServletRequest.class); bind(ServletResponse.class).to(HttpServletResponse.class); // inject the pipeline into GuiceFilter so it can route requests correctly // Unfortunate staticness... =( // NOTE(dhanji): This is maintained for legacy purposes. requestStaticInjection(GuiceFilter.class); bind(ManagedFilterPipeline.class); bind(ManagedServletPipeline.class); bind(FilterPipeline.class).to(ManagedFilterPipeline.class).asEagerSingleton(); bind(ServletContext.class).toProvider(BackwardsCompatibleServletContextProvider.class); } @Provides @RequestScoped HttpServletRequest provideHttpServletRequest() { return GuiceFilter.getRequest(); } @Provides @RequestScoped HttpServletResponse provideHttpServletResponse() { return GuiceFilter.getResponse(); } @Provides HttpSession provideHttpSession() { return GuiceFilter.getRequest().getSession(); } @SuppressWarnings({"unchecked"}) @Provides @RequestScoped @RequestParameters Map provideRequestParameters() { return GuiceFilter.getRequest().getParameterMap(); } @Override public boolean equals(Object o) { // Is only ever installed internally, so we don't need to check state. return o instanceof InternalServletModule; } @Override public int hashCode() { return InternalServletModule.class.hashCode(); } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java0000644000175000017500000001453111434212566031053 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Binding; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Maps; import com.google.inject.internal.util.Sets; import java.io.IOException; import java.util.List; import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * Central routing/dispatch class handles lifecycle of managed filters, and delegates to the servlet * pipeline. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @Singleton class ManagedFilterPipeline implements FilterPipeline{ private final FilterDefinition[] filterDefinitions; private final ManagedServletPipeline servletPipeline; private final Provider servletContext; //Unfortunately, we need the injector itself in order to create filters + servlets private final Injector injector; //Guards a DCL, so needs to be volatile private volatile boolean initialized = false; private static final TypeLiteral FILTER_DEFS = TypeLiteral.get(FilterDefinition.class); @Inject public ManagedFilterPipeline(Injector injector, ManagedServletPipeline servletPipeline, Provider servletContext) { this.injector = injector; this.servletPipeline = servletPipeline; this.servletContext = servletContext; this.filterDefinitions = collectFilterDefinitions(injector); } /** * Introspects the injector and collects all instances of bound {@code List} * into a master list. * * We have a guarantee that {@link com.google.inject.Injector#getBindings()} returns a map * that preserves insertion order in entry-set iterators. */ private FilterDefinition[] collectFilterDefinitions(Injector injector) { List filterDefinitions = Lists.newArrayList(); for (Binding entry : injector.findBindingsByType(FILTER_DEFS)) { filterDefinitions.add(entry.getProvider().get()); } // Convert to a fixed size array for speed. return filterDefinitions.toArray(new FilterDefinition[filterDefinitions.size()]); } public synchronized void initPipeline(ServletContext servletContext) throws ServletException { //double-checked lock, prevents duplicate initialization if (initialized) return; // Used to prevent duplicate initialization. Set initializedSoFar = Sets.newSetFromMap(Maps.newIdentityHashMap()); for (FilterDefinition filterDefinition : filterDefinitions) { filterDefinition.init(servletContext, injector, initializedSoFar); } //next, initialize servlets... servletPipeline.init(servletContext, injector); //everything was ok... initialized = true; } public void dispatch(ServletRequest request, ServletResponse response, FilterChain proceedingFilterChain) throws IOException, ServletException { //lazy init of filter pipeline (OK by the servlet specification). This is needed //in order for us not to force users to create a GuiceServletContextListener subclass. if (!initialized) { initPipeline(servletContext.get()); } //obtain the servlet pipeline to dispatch against new FilterChainInvocation(filterDefinitions, servletPipeline, proceedingFilterChain) .doFilter(withDispatcher(request, servletPipeline), response); } /** * Used to create an proxy that dispatches either to the guice-servlet pipeline or the regular * pipeline based on uri-path match. This proxy also provides minimal forwarding support. * * We cannot forward from a web.xml Servlet/JSP to a guice-servlet (because the filter pipeline * is not called again). However, we can wrap requests with our own dispatcher to forward the * *other* way. web.xml Servlets/JSPs can forward to themselves as per normal. * * This is not a problem cuz we intend for people to migrate from web.xml to guice-servlet, * incrementally, but not the other way around (which, we should actively discourage). */ @SuppressWarnings({ "JavaDoc", "deprecation" }) private ServletRequest withDispatcher(ServletRequest servletRequest, final ManagedServletPipeline servletPipeline) { HttpServletRequest request = (HttpServletRequest) servletRequest; // don't wrap the request if there are no servlets mapped. This prevents us from inserting our // wrapper unless it's actually going to be used. This is necessary for compatibility for apps // that downcast their HttpServletRequests to a concrete implementation. if (!servletPipeline.hasServletsMapped()) { return servletRequest; } //noinspection OverlyComplexAnonymousInnerClass return new HttpServletRequestWrapper(request) { @Override public RequestDispatcher getRequestDispatcher(String path) { final RequestDispatcher dispatcher = servletPipeline.getRequestDispatcher(path); return (null != dispatcher) ? dispatcher : super.getRequestDispatcher(path); } }; } public void destroyPipeline() { //destroy servlets first servletPipeline.destroy(); //go down chain and destroy all our filters Set destroyedSoFar = Sets.newSetFromMap(Maps.newIdentityHashMap()); for (FilterDefinition filterDefinition : filterDefinitions) { filterDefinition.destroy(destroyedSoFar); } } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/SessionScoped.java0000644000175000017500000000217611434007752027445 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.ScopeAnnotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Apply this to implementation classes when you want one instance per session. * * @see com.google.inject.Scopes#SINGLETON * @author crazybob@google.com (Bob Lee) */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @ScopeAnnotation public @interface SessionScoped {} guice-3.0/extensions/servlet/src/com/google/inject/servlet/ServletModuleBinding.java0000644000175000017500000000235611467446206030760 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.util.Map; /** * A binding created by {@link ServletModule}. * * @author sameb@google.com (Sam Berlin) * @since 3.0 */ public interface ServletModuleBinding { /** Returns the pattern type that this binding was created with. */ UriPatternType getUriPatternType(); /** Returns the pattern used to match against the binding. */ String getPattern(); /** Returns any context params supplied when creating the binding. */ Map getInitParams(); /** Returns true if the given URI will match this binding. */ boolean matchesUri(String uri); } guice-3.0/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java0000644000175000017500000001345611542601712030121 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Scopes; import com.google.inject.internal.util.Iterators; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import java.io.IOException; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import javax.servlet.Filter; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; /** * An internal representation of a filter definition against a particular URI pattern. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ class FilterDefinition implements ProviderWithExtensionVisitor { private final String pattern; private final Key filterKey; private final UriPatternMatcher patternMatcher; private final Map initParams; // set only if this was bound to an instance of a Filter. private final Filter filterInstance; // always set after init is called. private final AtomicReference filter = new AtomicReference(); public FilterDefinition(String pattern, Key filterKey, UriPatternMatcher patternMatcher, Map initParams, Filter filterInstance) { this.pattern = pattern; this.filterKey = filterKey; this.patternMatcher = patternMatcher; this.initParams = Collections.unmodifiableMap(new HashMap(initParams)); this.filterInstance = filterInstance; } public FilterDefinition get() { return this; } public V acceptExtensionVisitor(BindingTargetVisitor visitor, ProviderInstanceBinding binding) { if(visitor instanceof ServletModuleTargetVisitor) { if(filterInstance != null) { return ((ServletModuleTargetVisitor)visitor).visit( new InstanceFilterBindingImpl(initParams, pattern, filterInstance, patternMatcher)); } else { return ((ServletModuleTargetVisitor)visitor).visit( new LinkedFilterBindingImpl(initParams, pattern, filterKey, patternMatcher)); } } else { return visitor.visit(binding); } } private boolean shouldFilter(String uri) { return patternMatcher.matches(uri); } public void init(final ServletContext servletContext, Injector injector, Set initializedSoFar) throws ServletException { // This absolutely must be a singleton, and so is only initialized once. if (!Scopes.isSingleton(injector.getBinding(filterKey))) { throw new ServletException("Filters must be bound as singletons. " + filterKey + " was not bound in singleton scope."); } Filter filter = injector.getInstance(filterKey); this.filter.set(filter); // Only fire init() if this Singleton filter has not already appeared earlier // in the filter chain. if (initializedSoFar.contains(filter)) { return; } //initialize our filter with the configured context params and servlet context filter.init(new FilterConfig() { public String getFilterName() { return filterKey.toString(); } public ServletContext getServletContext() { return servletContext; } public String getInitParameter(String s) { return initParams.get(s); } public Enumeration getInitParameterNames() { return Iterators.asEnumeration(initParams.keySet().iterator()); } }); initializedSoFar.add(filter); } public void destroy(Set destroyedSoFar) { // filters are always singletons Filter reference = filter.get(); // Do nothing if this Filter was invalid (usually due to not being scoped // properly), or was already destroyed. According to Servlet Spec: it is // "out of service", and does not need to be destroyed. // Also prevent duplicate destroys to the same singleton that may appear // more than once on the filter chain. if (null == reference || destroyedSoFar.contains(reference)) { return; } try { reference.destroy(); } finally { destroyedSoFar.add(reference); } } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChainInvocation filterChainInvocation) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; final String path = request.getRequestURI().substring(request.getContextPath().length()); if (shouldFilter(path)) { filter.get() .doFilter(servletRequest, servletResponse, filterChainInvocation); } else { //otherwise proceed down chain anyway filterChainInvocation.doFilter(servletRequest, servletResponse); } } //VisibleForTesting Filter getFilter() { return filter.get(); } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/LinkedServletBinding.java0000644000175000017500000000175611467443276030750 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import javax.servlet.http.HttpServlet; import com.google.inject.Key; /** * A linked binding to a servlet. * * @author sameb@google.com * @since 3.0 */ public interface LinkedServletBinding extends ServletModuleBinding { /** Returns the key used to lookup the servlet instance. */ Key getLinkedKey(); } guice-3.0/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBinding.java0000644000175000017500000000173411467443340030535 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import javax.servlet.Filter; import com.google.inject.Key; /** * A linked binding to a filter. * * @author sameb@google.com * @since 3.0 */ public interface LinkedFilterBinding extends ServletModuleBinding { /** Returns the key used to lookup the filter instance. */ Key getLinkedKey(); } guice-3.0/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java0000644000175000017500000001547211434212566031257 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Binding; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Maps; import com.google.inject.internal.util.Preconditions; import com.google.inject.internal.util.Sets; import java.io.IOException; import java.util.List; import java.util.Set; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * A wrapping dispatcher for servlets, in much the same way as {@link ManagedFilterPipeline} is for * filters. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @Singleton class ManagedServletPipeline { private final ServletDefinition[] servletDefinitions; private static final TypeLiteral SERVLET_DEFS = TypeLiteral.get(ServletDefinition.class); @Inject public ManagedServletPipeline(Injector injector) { this.servletDefinitions = collectServletDefinitions(injector); } boolean hasServletsMapped() { return servletDefinitions.length > 0; } /** * Introspects the injector and collects all instances of bound {@code List} * into a master list. * * We have a guarantee that {@link com.google.inject.Injector#getBindings()} returns a map * that preserves insertion order in entry-set iterators. */ private ServletDefinition[] collectServletDefinitions(Injector injector) { List servletDefinitions = Lists.newArrayList(); for (Binding entry : injector.findBindingsByType(SERVLET_DEFS)) { servletDefinitions.add(entry.getProvider().get()); } // Copy to a fixed size array for speed. return servletDefinitions.toArray(new ServletDefinition[servletDefinitions.size()]); } public void init(ServletContext servletContext, Injector injector) throws ServletException { Set initializedSoFar = Sets.newSetFromMap(Maps.newIdentityHashMap()); for (ServletDefinition servletDefinition : servletDefinitions) { servletDefinition.init(servletContext, injector, initializedSoFar); } } public boolean service(ServletRequest request, ServletResponse response) throws IOException, ServletException { //stop at the first matching servlet and service for (ServletDefinition servletDefinition : servletDefinitions) { if (servletDefinition.service(request, response)) { return true; } } //there was no match... return false; } public void destroy() { Set destroyedSoFar = Sets.newSetFromMap(Maps.newIdentityHashMap()); for (ServletDefinition servletDefinition : servletDefinitions) { servletDefinition.destroy(destroyedSoFar); } } /** * @return Returns a request dispatcher wrapped with a servlet mapped to * the given path or null if no mapping was found. */ RequestDispatcher getRequestDispatcher(String path) { final String newRequestUri = path; // TODO(dhanji): check servlet spec to see if the following is legal or not. // Need to strip query string if requested... for (final ServletDefinition servletDefinition : servletDefinitions) { if (servletDefinition.shouldServe(path)) { return new RequestDispatcher() { public void forward(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { Preconditions.checkState(!servletResponse.isCommitted(), "Response has been committed--you can only call forward before" + " committing the response (hint: don't flush buffers)"); // clear buffer before forwarding servletResponse.resetBuffer(); ServletRequest requestToProcess; if (servletRequest instanceof HttpServletRequest) { requestToProcess = new RequestDispatcherRequestWrapper(servletRequest, newRequestUri); } else { // This should never happen, but instead of throwing an exception // we will allow a happy case pass thru for maximum tolerance to // legacy (and internal) code. requestToProcess = servletRequest; } servletRequest.setAttribute(REQUEST_DISPATCHER_REQUEST, Boolean.TRUE); // now dispatch to the servlet try { servletDefinition.doService(requestToProcess, servletResponse); } finally { servletRequest.removeAttribute(REQUEST_DISPATCHER_REQUEST); } } public void include(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { servletRequest.setAttribute(REQUEST_DISPATCHER_REQUEST, Boolean.TRUE); // route to the target servlet try { servletDefinition.doService(servletRequest, servletResponse); } finally { servletRequest.removeAttribute(REQUEST_DISPATCHER_REQUEST); } } }; } } //otherwise, can't process return null; } /** * A Marker constant attribute that when present in the request indicates to Guice servlet that * this request has been generated by a request dispatcher rather than the servlet pipeline. * In accordance with section 8.4.2 of the Servlet 2.4 specification. */ public static final String REQUEST_DISPATCHER_REQUEST = "javax.servlet.forward.servlet_path"; private static class RequestDispatcherRequestWrapper extends HttpServletRequestWrapper { private final String newRequestUri; public RequestDispatcherRequestWrapper(ServletRequest servletRequest, String newRequestUri) { super((HttpServletRequest) servletRequest); this.newRequestUri = newRequestUri; } @Override public String getRequestURI() { return newRequestUri; } } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/ServletsModuleBuilder.java0000644000175000017500000001115611434254052031143 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.AbstractModule; import com.google.inject.Key; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Sets; import com.google.inject.internal.UniqueAnnotations; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServlet; /** * Builds the guice module that binds configured servlets, with their * wrapper ServletDefinitions. Is part of the binding EDSL. Very similar to * {@link com.google.inject.servlet.FiltersModuleBuilder}. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ class ServletsModuleBuilder extends AbstractModule { private final List servletDefinitions = Lists.newArrayList(); private final List servletInstanceEntries = Lists.newArrayList(); //invoked on injector config @Override protected void configure() { // Create bindings for servlet instances for (ServletInstanceBindingEntry entry : servletInstanceEntries) { bind(entry.key).toInstance(entry.servlet); } // Ensure that servlets are not bound twice to the same pattern. Set servletUris = Sets.newHashSet(); for (ServletDefinition servletDefinition : servletDefinitions) { if (servletUris.contains(servletDefinition.getPattern())) { addError("More than one servlet was mapped to the same URI pattern: " + servletDefinition.getPattern()); } else { bind(Key.get(ServletDefinition.class, UniqueAnnotations.create())).toProvider(servletDefinition); servletUris.add(servletDefinition.getPattern()); } } } //the first level of the EDSL-- public ServletModule.ServletKeyBindingBuilder serve(List urlPatterns) { return new ServletKeyBindingBuilderImpl(urlPatterns, UriPatternType.SERVLET); } public ServletModule.ServletKeyBindingBuilder serveRegex(List regexes) { return new ServletKeyBindingBuilderImpl(regexes, UriPatternType.REGEX); } private static class ServletInstanceBindingEntry { final Key key; final HttpServlet servlet; ServletInstanceBindingEntry(Key key, HttpServlet servlet) { this.key = key; this.servlet = servlet; } } //non-static inner class so it can access state of enclosing module class class ServletKeyBindingBuilderImpl implements ServletModule.ServletKeyBindingBuilder { private final List uriPatterns; private final UriPatternType uriPatternType; private ServletKeyBindingBuilderImpl(List uriPatterns, UriPatternType uriPatternType) { this.uriPatterns = uriPatterns; this.uriPatternType = uriPatternType; } public void with(Class servletKey) { with(Key.get(servletKey)); } public void with(Key servletKey) { with(servletKey, new HashMap()); } public void with(HttpServlet servlet) { with(servlet, new HashMap()); } public void with(Class servletKey, Map initParams) { with(Key.get(servletKey), initParams); } public void with(Key servletKey, Map initParams) { with(servletKey, initParams, null); } private void with(Key servletKey, Map initParams, HttpServlet servletInstance) { for (String pattern : uriPatterns) { servletDefinitions.add( new ServletDefinition(pattern, servletKey, UriPatternType.get(uriPatternType, pattern), initParams, servletInstance)); } } public void with(HttpServlet servlet, Map initParams) { Key servletKey = Key.get(HttpServlet.class, UniqueAnnotations.create()); servletInstanceEntries.add(new ServletInstanceBindingEntry(servletKey, servlet)); with(servletKey, initParams, servlet); } } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/RequestParameters.java0000644000175000017500000000225511434007752030336 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.BindingAnnotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Apply this to field or parameters of type {@code Map} * when you want the HTTP request parameter map to be injected. * * @author crazybob@google.com (Bob Lee) */ @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation public @interface RequestParameters {} guice-3.0/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBinding.java0000644000175000017500000000167411467443262031101 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import javax.servlet.Filter; /** * A binding to a single instance of a filter. * * @author sameb@google.com * @since 3.0 */ public interface InstanceFilterBinding extends ServletModuleBinding { /** Returns the filter instance that will be used. */ Filter getFilterInstance(); } guice-3.0/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java0000644000175000017500000002224011542600050030301 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Scopes; import com.google.inject.internal.util.Iterators; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import java.io.IOException; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST; /** * An internal representation of a servlet definition mapped to a particular URI pattern. Also * performs the request dispatch to that servlet. How nice and OO =) * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ class ServletDefinition implements ProviderWithExtensionVisitor { private final String pattern; private final Key servletKey; private final UriPatternMatcher patternMatcher; private final Map initParams; // set only if this was bound using a servlet instance. private final HttpServlet servletInstance; //always set in init, our servlet is always presumed to be a singleton private final AtomicReference httpServlet = new AtomicReference(); public ServletDefinition(String pattern, Key servletKey, UriPatternMatcher patternMatcher, Map initParams, HttpServlet servletInstance) { this.pattern = pattern; this.servletKey = servletKey; this.patternMatcher = patternMatcher; this.initParams = Collections.unmodifiableMap(new HashMap(initParams)); this.servletInstance = servletInstance; } public ServletDefinition get() { return this; } public V acceptExtensionVisitor(BindingTargetVisitor visitor, ProviderInstanceBinding binding) { if(visitor instanceof ServletModuleTargetVisitor) { if(servletInstance != null) { return ((ServletModuleTargetVisitor)visitor).visit( new InstanceServletBindingImpl(initParams, pattern, servletInstance, patternMatcher)); } else { return ((ServletModuleTargetVisitor)visitor).visit( new LinkedServletBindingImpl(initParams, pattern, servletKey, patternMatcher)); } } else { return visitor.visit(binding); } } boolean shouldServe(String uri) { return patternMatcher.matches(uri); } public void init(final ServletContext servletContext, Injector injector, Set initializedSoFar) throws ServletException { // This absolutely must be a singleton, and so is only initialized once. if (!Scopes.isSingleton(injector.getBinding(servletKey))) { throw new ServletException("Servlets must be bound as singletons. " + servletKey + " was not bound in singleton scope."); } HttpServlet httpServlet = injector.getInstance(servletKey); this.httpServlet.set(httpServlet); // Only fire init() if we have not appeared before in the filter chain. if (initializedSoFar.contains(httpServlet)) { return; } //initialize our servlet with the configured context params and servlet context httpServlet.init(new ServletConfig() { public String getServletName() { return servletKey.toString(); } public ServletContext getServletContext() { return servletContext; } public String getInitParameter(String s) { return initParams.get(s); } public Enumeration getInitParameterNames() { return Iterators.asEnumeration(initParams.keySet().iterator()); } }); // Mark as initialized. initializedSoFar.add(httpServlet); } public void destroy(Set destroyedSoFar) { HttpServlet reference = httpServlet.get(); // Do nothing if this Servlet was invalid (usually due to not being scoped // properly). According to Servlet Spec: it is "out of service", and does not // need to be destroyed. // Also prevent duplicate destroys to the same singleton that may appear // more than once on the filter chain. if (null == reference || destroyedSoFar.contains(reference)) { return; } try { reference.destroy(); } finally { destroyedSoFar.add(reference); } } /** * Wrapper around the service chain to ensure a servlet is servicing what it must and provides it * with a wrapped request. * * @return Returns true if this servlet triggered for the given request. Or false if * guice-servlet should continue dispatching down the servlet pipeline. * * @throws IOException If thrown by underlying servlet * @throws ServletException If thrown by underlying servlet */ public boolean service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; final String path = request.getRequestURI().substring(request.getContextPath().length()); final boolean serve = shouldServe(path); //invocations of the chain end at the first matched servlet if (serve) { doService(servletRequest, servletResponse); } //return false if no servlet matched (so we can proceed down to the web.xml servlets) return serve; } /** * Utility that delegates to the actual service method of the servlet wrapped with a contextual * request (i.e. with correctly computed path info). * * We need to suppress deprecation coz we use HttpServletRequestWrapper, which implements * deprecated API for backwards compatibility. */ void doService(final ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { HttpServletRequest request = new HttpServletRequestWrapper( (HttpServletRequest) servletRequest) { private String path; private boolean pathComputed = false; //must use a boolean on the memo field, because null is a legal value (TODO no, it's not) private boolean pathInfoComputed = false; private String pathInfo; @Override public String getPathInfo() { if (!isPathInfoComputed()) { int servletPathLength = getServletPath().length(); pathInfo = getRequestURI().substring(getContextPath().length()).replaceAll("[/]{2,}", "/"); pathInfo = pathInfo.length() > servletPathLength ? pathInfo.substring(servletPathLength) : null; // Corner case: when servlet path and request path match exactly (without trailing '/'), // then pathinfo is null if ("".equals(pathInfo) && servletPathLength != 0) { pathInfo = null; } pathInfoComputed = true; } return pathInfo; } // NOTE(dhanji): These two are a bit of a hack to help ensure that request dipatcher-sent // requests don't use the same path info that was memoized for the original request. private boolean isPathInfoComputed() { return pathInfoComputed && !(null != servletRequest.getAttribute(REQUEST_DISPATCHER_REQUEST)); } private boolean isPathComputed() { return pathComputed && !(null != servletRequest.getAttribute(REQUEST_DISPATCHER_REQUEST)); } @Override public String getServletPath() { return computePath(); } @Override public String getPathTranslated() { final String info = getPathInfo(); return (null == info) ? null : getRealPath(info); } // Memoizer pattern. private String computePath() { if (!isPathComputed()) { String servletPath = super.getServletPath(); path = patternMatcher.extractPath(servletPath); pathComputed = true; if (null == path) { path = servletPath; } } return path; } }; httpServlet.get().service(request, servletResponse); } String getKey() { return servletKey.toString(); } String getPattern() { return pattern; } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/InstanceFilterBindingImpl.java0000644000175000017500000000305411467443654031722 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.util.Map; import javax.servlet.Filter; import com.google.inject.internal.util.ToStringBuilder; /** * Default implementation of InstanceFilterBinding. * * @author sameb@google.com (Sam Berlin) */ class InstanceFilterBindingImpl extends AbstractServletModuleBinding implements InstanceFilterBinding { InstanceFilterBindingImpl(Map initParams, String pattern, Filter target, UriPatternMatcher patternMatcher) { super(initParams, pattern, target, patternMatcher); } public Filter getFilterInstance() { return getTarget(); } @Override public String toString() { return new ToStringBuilder(InstanceFilterBinding.class) .add("pattern", getPattern()) .add("initParams", getInitParams()) .add("uriPatternType", getUriPatternType()) .add("filterInstance", getFilterInstance()) .toString(); } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/ServletModuleTargetVisitor.java0000644000175000017500000000466711463267560032223 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.inject.servlet; import javax.servlet.Filter; import javax.servlet.http.HttpServlet; import com.google.inject.servlet.ServletModule.FilterKeyBindingBuilder; import com.google.inject.servlet.ServletModule.ServletKeyBindingBuilder; import com.google.inject.spi.BindingTargetVisitor; /** * A visitor for the servlet extension. * * If your {@link BindingTargetVisitor} implements this interface, bindings created by using * {@link ServletModule} will be visited through this interface. * * @since 3.0 * @author sameb@google.com (Sam Berlin) */ public interface ServletModuleTargetVisitor extends BindingTargetVisitor { /** * Visits a filter binding created by {@link ServletModule#filter}, where * {@link FilterKeyBindingBuilder#through} is called with a Class or Key. * * If multiple patterns were specified, this will be called multiple times. */ V visit(LinkedFilterBinding binding); /** * Visits a filter binding created by {@link ServletModule#filter} where * {@link FilterKeyBindingBuilder#through} is called with a {@link Filter}. * * If multiple patterns were specified, this will be called multiple times. */ V visit(InstanceFilterBinding binding); /** * Visits a servlet binding created by {@link ServletModule#serve} where * {@link ServletKeyBindingBuilder#with}, is called with a Class or Key. * * If multiple patterns were specified, this will be called multiple times. */ V visit(LinkedServletBinding binding); /** * Visits a servlet binding created by {@link ServletModule#serve} where * {@link ServletKeyBindingBuilder#with}, is called with an {@link HttpServlet}. * * If multiple patterns were specified, this will be called multiple times. */ V visit(InstanceServletBinding binding); }guice-3.0/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java0000644000175000017500000001434011434007752027062 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Inject; import com.google.inject.OutOfScopeException; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.logging.Logger; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** *

* Apply this filter in web.xml above all other filters (typically), to all requests where you plan * to use servlet scopes. This is also needed in order to dispatch requests to injectable filters * and servlets: *

 *  <filter>
 *    <filter-name>guiceFilter</filter-name>
 *    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
 *  </filter>
 *
 *  <filter-mapping>
 *    <filter-name>guiceFilter</filter-name>
 *    <url-pattern>/*</url-pattern>
 *  </filter-mapping>
 *  
* * This filter must appear before every filter that makes use of Guice injection or servlet * scopes functionality. Typically, you will only register this filter in web.xml and register * any other filters (and servlets) using a {@link ServletModule}. * * @author crazybob@google.com (Bob Lee) * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class GuiceFilter implements Filter { static final ThreadLocal localContext = new ThreadLocal(); static volatile FilterPipeline pipeline = new DefaultFilterPipeline(); /** * We allow both the static and dynamic versions of the pipeline to exist. */ @Inject private final FilterPipeline injectedPipeline = null; /** Used to inject the servlets configured via {@link ServletModule} */ static volatile WeakReference servletContext = new WeakReference(null); private static final String MULTIPLE_INJECTORS_WARNING = "Multiple Servlet injectors detected. This is a warning " + "indicating that you have more than one " + GuiceFilter.class.getSimpleName() + " running " + "in your web application. If this is deliberate, you may safely " + "ignore this message. If this is NOT deliberate however, " + "your application may not work as expected."; //VisibleForTesting @Inject static void setPipeline(FilterPipeline pipeline) { // This can happen if you create many injectors and they all have their own // servlet module. This is legal, caveat a small warning. if (GuiceFilter.pipeline instanceof ManagedFilterPipeline) { Logger.getLogger(GuiceFilter.class.getName()).warning(MULTIPLE_INJECTORS_WARNING); } // We overwrite the default pipeline GuiceFilter.pipeline = pipeline; } //VisibleForTesting static void reset() { pipeline = new DefaultFilterPipeline(); } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { Context previous = localContext.get(); // Prefer the injected pipeline, but fall back on the static one for web.xml users. FilterPipeline filterPipeline = null != injectedPipeline ? injectedPipeline : pipeline; try { localContext.set(new Context((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse)); //dispatch across the servlet pipeline, ensuring web.xml's filterchain is honored filterPipeline.dispatch(servletRequest, servletResponse, filterChain); } finally { localContext.set(previous); } } static HttpServletRequest getRequest() { return getContext().getRequest(); } static HttpServletResponse getResponse() { return getContext().getResponse(); } static ServletContext getServletContext() { return servletContext.get(); } static Context getContext() { Context context = localContext.get(); if (context == null) { throw new OutOfScopeException("Cannot access scoped object. Either we" + " are not currently inside an HTTP Servlet request, or you may" + " have forgotten to apply " + GuiceFilter.class.getName() + " as a servlet filter for this request."); } return context; } static class Context { final HttpServletRequest request; final HttpServletResponse response; Context(HttpServletRequest request, HttpServletResponse response) { this.request = request; this.response = response; } HttpServletRequest getRequest() { return request; } HttpServletResponse getResponse() { return response; } } public void init(FilterConfig filterConfig) throws ServletException { final ServletContext servletContext = filterConfig.getServletContext(); // Store servlet context in a weakreference, for injection GuiceFilter.servletContext = new WeakReference(servletContext); // In the default pipeline, this is a noop. However, if replaced // by a managed pipeline, a lazy init will be triggered the first time // dispatch occurs. FilterPipeline filterPipeline = null != injectedPipeline ? injectedPipeline : pipeline; filterPipeline.initPipeline(servletContext); } public void destroy() { try { // Destroy all registered filters & servlets in that order FilterPipeline filterPipeline = null != injectedPipeline ? injectedPipeline : pipeline; filterPipeline.destroyPipeline(); } finally { reset(); servletContext.clear(); } } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java0000644000175000017500000000335211434007752027574 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.ImplementedBy; import javax.servlet.ServletContext; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.FilterChain; import javax.servlet.ServletException; import java.io.IOException; /** * An internal dispatcher for guice-servlet registered servlets and filters. * By default, we assume a Guice 1.0 style servlet module is in play. In other * words, we dispatch directly to the web.xml pipeline after setting up scopes. * *

* If on the other hand, {@link ServletModule} is used to register managed * servlets and/or filters, then a different pipeline is bound instead. Which, * after dispatching to Guice-injected filters and servlets continues to the web.xml * pipeline (if necessary). * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @ImplementedBy(DefaultFilterPipeline.class) interface FilterPipeline { void initPipeline(ServletContext context) throws ServletException; void destroyPipeline(); void dispatch(ServletRequest request, ServletResponse response, FilterChain defaultFilterChain) throws IOException, ServletException; } guice-3.0/extensions/servlet/src/com/google/inject/servlet/GuiceServletContextListener.java0000644000175000017500000000444611434007752032342 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Injector; import java.lang.ref.WeakReference; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; /** * As of Guice 2.0 you can still use (your subclasses of) {@code GuiceServletContextListener} * class as a logical place to create and configure your injector. This will ensure the injector * is created when the web application is deployed. * * @author Kevin Bourrillion (kevinb@google.com) * @since 2.0 */ public abstract class GuiceServletContextListener implements ServletContextListener { static final String INJECTOR_NAME = Injector.class.getName(); public void contextInitialized(ServletContextEvent servletContextEvent) { final ServletContext servletContext = servletContextEvent.getServletContext(); // Set the Servletcontext early for those people who are using this class. // NOTE(dhanji): This use of the servletContext is deprecated. GuiceFilter.servletContext = new WeakReference(servletContext); Injector injector = getInjector(); injector.getInstance(InternalServletModule.BackwardsCompatibleServletContextProvider.class) .set(servletContext); servletContext.setAttribute(INJECTOR_NAME, injector); } public void contextDestroyed(ServletContextEvent servletContextEvent) { ServletContext servletContext = servletContextEvent.getServletContext(); servletContext.removeAttribute(INJECTOR_NAME); } /** * Override this method to create (or otherwise obtain a reference to) your * injector. */ protected abstract Injector getInjector(); } guice-3.0/extensions/servlet/src/com/google/inject/servlet/LinkedFilterBindingImpl.java0000644000175000017500000000315111467443676031366 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.util.Map; import javax.servlet.Filter; import com.google.inject.Key; import com.google.inject.internal.util.ToStringBuilder; /** * Default implementation of LinkedFilterBinding. * * @author sameb@google.com (Sam Berlin) */ class LinkedFilterBindingImpl extends AbstractServletModuleBinding> implements LinkedFilterBinding { LinkedFilterBindingImpl(Map initParams, String pattern, Key target, UriPatternMatcher patternMatcher) { super(initParams, pattern, target, patternMatcher); } public Key getLinkedKey() { return getTarget(); } @Override public String toString() { return new ToStringBuilder(LinkedFilterBinding.class) .add("pattern", getPattern()) .add("initParams", getInitParams()) .add("uriPatternType", getUriPatternType()) .add("linkedFilterKey", getLinkedKey()) .toString(); } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/ServletModule.java0000644000175000017500000002515311530541660027454 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import static com.google.inject.internal.util.Preconditions.checkState; import com.google.inject.AbstractModule; import com.google.inject.Key; import com.google.inject.internal.util.Lists; import java.util.Map; import javax.servlet.Filter; import javax.servlet.ServletContext; import javax.servlet.http.HttpServlet; /** * Configures the servlet scopes and creates bindings for the servlet API * objects so you can inject the request, response, session, etc. * *

* You should subclass this module to register servlets and * filters in the {@link #configureServlets()} method. * * @author crazybob@google.com (Bob Lee) * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class ServletModule extends AbstractModule { @Override protected final void configure() { checkState(filtersModuleBuilder == null, "Re-entry is not allowed."); checkState(servletsModuleBuilder == null, "Re-entry is not allowed."); filtersModuleBuilder = new FiltersModuleBuilder(); servletsModuleBuilder = new ServletsModuleBuilder(); try { // Install common bindings (skipped if already installed). install(new InternalServletModule()); // Install local filter and servlet bindings. configureServlets(); install(filtersModuleBuilder); install(servletsModuleBuilder); } finally { filtersModuleBuilder = null; servletsModuleBuilder = null; } } /** *

Servlet Mapping EDSL

* *

Part of the EDSL builder language for configuring servlets * and filters with guice-servlet. Think of this as an in-code replacement for web.xml. * Filters and servlets are configured here using simple java method calls. Here is a typical * example of registering a filter when creating your Guice injector: * *

   *   Guice.createInjector(..., new ServletModule() {
   *
   *     {@literal @}Override
   *     protected void configureServlets() {
   *       serve("*.html").with(MyServlet.class)
   *     }
   *   }
   * 
* * This registers a servlet (subclass of {@code HttpServlet}) called {@code MyServlet} to service * any web pages ending in {@code .html}. You can also use a path-style syntax to register * servlets: * *
   *       serve("/my/*").with(MyServlet.class)
   * 
* * Every servlet (or filter) is required to be a singleton. If you cannot annotate the class * directly, you should add a separate {@code bind(..).in(Singleton.class)} rule elsewhere in * your module. Mapping a servlet that is bound under any other scope is an error. * *

*

Dispatch Order

* You are free to register as many servlets and filters as you like this way. They will * be compared and dispatched in the order in which the filter methods are called: * *
   *
   *   Guice.createInjector(..., new ServletModule() {
   *
   *     {@literal @}Override
   *     protected void configureServlets() {
   *       filter("/*").through(MyFilter.class);
   *       filter("*.css").through(MyCssFilter.class);
   *       filter("*.jpg").through(new MyJpgFilter());
   *       // etc..
   *
   *       serve("*.html").with(MyServlet.class);
   *       serve("/my/*").with(MyServlet.class);
   *       serve("*.jpg").with(new MyServlet());
   *       // etc..
   *      }
   *    }
   * 
* This will traverse down the list of rules in lexical order. For example, a url * "{@code /my/file.js}" (after it runs through the matching filters) will first * be compared against the servlet mapping: * *
   *       serve("*.html").with(MyServlet.class);
   * 
* And failing that, it will descend to the next servlet mapping: * *
   *       serve("/my/*").with(MyServlet.class);
   * 
* * Since this rule matches, Guice Servlet will dispatch to {@code MyServlet}. These * two mapping rules can also be written in more compact form using varargs syntax: * *
   *       serve("*.html", "/my/*").with(MyServlet.class);
   * 
* * This way you can map several URI patterns to the same servlet. A similar syntax is * also available for filter mappings. * *

*

Regular Expressions

* You can also map servlets (or filters) to URIs using regular expressions: *
   *    serveRegex("(.)*ajax(.)*").with(MyAjaxServlet.class)
   * 
* * This will map any URI containing the text "ajax" in it to {@code MyAjaxServlet}. Such as: *
    *
  • http://www.google.com/ajax.html
  • *
  • http://www.google.com/content/ajax/index
  • *
  • http://www.google.com/it/is_totally_ajaxian
  • *
* * *

Initialization Parameters

* * Servlets (and filters) allow you to pass in init params * using the {@code } tag in web.xml. You can similarly pass in parameters to * Servlets and filters registered in Guice-servlet using a {@link java.util.Map} of parameter * name/value pairs. For example, to initialize {@code MyServlet} with two parameters * ({@code name="Dhanji", site="google.com"}) you could write: * *
   *  Map<String, String> params = new HashMap<String, String>();
   *  params.put("name", "Dhanji");
   *  params.put("site", "google.com");
   *
   *  ...
   *      serve("/*").with(MyServlet.class, params)
   * 
* *

*

Binding Keys

* * You can also bind keys rather than classes. This lets you hide * implementations with package-local visbility and expose them using * only a Guice module and an annotation: * *
   *  ...
   *      filter("/*").through(Key.get(Filter.class, Fave.class));
   * 
* * Where {@code Filter.class} refers to the Servlet API interface and {@code Fave.class} is a * custom binding annotation. Elsewhere (in one of your own modules) you can bind this * filter's implementation: * *
   *   bind(Filter.class).annotatedWith(Fave.class).to(MyFilterImpl.class);
   * 
* * See {@link com.google.inject.Binder} for more information on binding syntax. * *

*

Multiple Modules

* * It is sometimes useful to capture servlet and filter mappings from multiple different * modules. This is essential if you want to package and offer drop-in Guice plugins that * provide servlet functionality. * *

* Guice Servlet allows you to register several instances of {@code ServletModule} to your * injector. The order in which these modules are installed determines the dispatch order * of filters and the precedence order of servlets. For example, if you had two servlet modules, * {@code RpcModule} and {@code WebServiceModule} and they each contained a filter that mapped * to the same URI pattern, {@code "/*"}: * *

* In {@code RpcModule}: *

   *     filter("/*").through(RpcFilter.class);
   * 
* * In {@code WebServiceModule}: *
   *     filter("/*").through(WebServiceFilter.class);
   * 
* * Then the order in which these filters are dispatched is determined by the order in which * the modules are installed: * *
   *   install(new WebServiceModule());
   *   install(new RpcModule());
   * 
* * In the case shown above {@code WebServiceFilter} will run first. * * @since 2.0 */ protected void configureServlets() { } private FiltersModuleBuilder filtersModuleBuilder; private ServletsModuleBuilder servletsModuleBuilder; /** * @param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc. * @since 2.0 */ protected final FilterKeyBindingBuilder filter(String urlPattern, String... morePatterns) { return filtersModuleBuilder.filter(Lists.newArrayList(urlPattern, morePatterns)); } /** * @param regex Any Java-style regular expression. * @since 2.0 */ protected final FilterKeyBindingBuilder filterRegex(String regex, String... regexes) { return filtersModuleBuilder.filterRegex(Lists.newArrayList(regex, regexes)); } /** * @param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc. * @since 2.0 */ protected final ServletKeyBindingBuilder serve(String urlPattern, String... morePatterns) { return servletsModuleBuilder.serve(Lists.newArrayList(urlPattern, morePatterns)); } /** * @param regex Any Java-style regular expression. * @since 2.0 */ protected final ServletKeyBindingBuilder serveRegex(String regex, String... regexes) { return servletsModuleBuilder.serveRegex(Lists.newArrayList(regex, regexes)); } /** * This method only works if you are using the {@linkplain GuiceServletContextListener} to * create your injector. Otherwise, it returns null. * @return The current servlet context. * @since 3.0 */ protected final ServletContext getServletContext() { return GuiceFilter.getServletContext(); } /** * See the EDSL examples at {@link ServletModule#configureServlets()} * * @since 2.0 */ public static interface FilterKeyBindingBuilder { void through(Class filterKey); void through(Key filterKey); /** @since 3.0 */ void through(Filter filter); void through(Class filterKey, Map initParams); void through(Key filterKey, Map initParams); /** @since 3.0 */ void through(Filter filter, Map initParams); } /** * See the EDSL examples at {@link ServletModule#configureServlets()} * * @since 2.0 */ public static interface ServletKeyBindingBuilder { void with(Class servletKey); void with(Key servletKey); /** @since 3.0 */ void with(HttpServlet servlet); void with(Class servletKey, Map initParams); void with(Key servletKey, Map initParams); /** @since 3.0 */ void with(HttpServlet servlet, Map initParams); } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java0000644000175000017500000000745411464214062027624 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * An enumeration of the available URI-pattern matching styles * * @since 3.0 */ public enum UriPatternType { SERVLET, REGEX; static UriPatternMatcher get(UriPatternType type, String pattern) { switch (type) { case SERVLET: return new ServletStyleUriPatternMatcher(pattern); case REGEX: return new RegexUriPatternMatcher(pattern); default: return null; } } /** * Matches URIs using the pattern grammar of the Servlet API and web.xml. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ private static class ServletStyleUriPatternMatcher implements UriPatternMatcher { private final String pattern; private final Kind patternKind; private static enum Kind { PREFIX, SUFFIX, LITERAL, } public ServletStyleUriPatternMatcher(String pattern) { if (pattern.startsWith("*")) { this.pattern = pattern.substring(1); this.patternKind = Kind.PREFIX; } else if (pattern.endsWith("*")) { this.pattern = pattern.substring(0, pattern.length() - 1); this.patternKind = Kind.SUFFIX; } else { this.pattern = pattern; this.patternKind = Kind.LITERAL; } } public boolean matches(String uri) { if (null == uri) { return false; } if (patternKind == Kind.PREFIX) { return uri.endsWith(pattern); } else if (patternKind == Kind.SUFFIX) { return uri.startsWith(pattern); } //else treat as a literal return pattern.equals(uri); } public String extractPath(String path) { if (patternKind == Kind.PREFIX) { return null; } else if (patternKind == Kind.SUFFIX) { String extract = pattern; //trim the trailing '/' if (extract.endsWith("/")) { extract = extract.substring(0, extract.length() - 1); } return extract; } //else treat as literal return path; } public UriPatternType getPatternType() { return UriPatternType.SERVLET; } } /** * Matches URIs using a regular expression. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ private static class RegexUriPatternMatcher implements UriPatternMatcher { private final Pattern pattern; public RegexUriPatternMatcher(String pattern) { this.pattern = Pattern.compile(pattern); } public boolean matches(String uri) { return null != uri && this.pattern.matcher(uri).matches(); } public String extractPath(String path) { Matcher matcher = pattern.matcher(path); if (matcher.matches() && matcher.groupCount() >= 1) { // Try to capture the everything before the regex begins to match // the path. This is a rough approximation to try and get parity // with the servlet style mapping where the path is a capture of // the URI before the wildcard. int end = matcher.start(1); if (end < path.length()) { return path.substring(0, end); } } return null; } public UriPatternType getPatternType() { return UriPatternType.REGEX; } } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/FiltersModuleBuilder.java0000644000175000017500000001031311434253770030744 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.AbstractModule; import com.google.inject.Key; import com.google.inject.internal.util.Lists; import com.google.inject.internal.UniqueAnnotations; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.Filter; /** * Builds the guice module that binds configured filters, with their * wrapper FilterDefinitions. Is part of the binding EDSL. All Filters * and Servlets are always bound as singletons. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ class FiltersModuleBuilder extends AbstractModule { private final List filterDefinitions = Lists.newArrayList(); private final List filterInstanceEntries = Lists.newArrayList(); //invoked on injector config @Override protected void configure() { // Create bindings for filter instances for (FilterInstanceBindingEntry entry : filterInstanceEntries) { bind(entry.key).toInstance(entry.filter); } // Bind these filter definitions to a unique random key. Doesn't matter what it is, // coz it's never used. for(FilterDefinition fd : filterDefinitions) { bind(FilterDefinition.class).annotatedWith(UniqueAnnotations.create()).toProvider(fd); } } public ServletModule.FilterKeyBindingBuilder filter(List patterns) { return new FilterKeyBindingBuilderImpl(patterns, UriPatternType.SERVLET); } public ServletModule.FilterKeyBindingBuilder filterRegex(List regexes) { return new FilterKeyBindingBuilderImpl(regexes, UriPatternType.REGEX); } private static class FilterInstanceBindingEntry { final Key key; final Filter filter; FilterInstanceBindingEntry(Key key, Filter filter) { this.key = key; this.filter = filter; } } //non-static inner class so it can access state of enclosing module class class FilterKeyBindingBuilderImpl implements ServletModule.FilterKeyBindingBuilder { private final List uriPatterns; private final UriPatternType uriPatternType; private FilterKeyBindingBuilderImpl(List uriPatterns, UriPatternType uriPatternType) { this.uriPatterns = uriPatterns; this.uriPatternType = uriPatternType; } public void through(Class filterKey) { through(Key.get(filterKey)); } public void through(Key filterKey) { through(filterKey, new HashMap()); } public void through(Filter filter) { through(filter, new HashMap()); } public void through(Class filterKey, Map initParams) { // Careful you don't accidentally make this method recursive, thank you IntelliJ IDEA! through(Key.get(filterKey), initParams); } public void through(Key filterKey, Map initParams) { through(filterKey, initParams, null); } private void through(Key filterKey, Map initParams, Filter filterInstance) { for (String pattern : uriPatterns) { filterDefinitions.add( new FilterDefinition(pattern, filterKey, UriPatternType.get(uriPatternType, pattern), initParams, filterInstance)); } } public void through(Filter filter, Map initParams) { Key filterKey = Key.get(Filter.class, UniqueAnnotations.create()); filterInstanceEntries.add(new FilterInstanceBindingEntry(filterKey, filter)); through(filterKey, initParams, filter); } } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/LinkedServletBindingImpl.java0000644000175000017500000000320611467443726031562 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.util.Map; import javax.servlet.http.HttpServlet; import com.google.inject.Key; import com.google.inject.internal.util.ToStringBuilder; /** * Default implementation of LinkedServletBinding. * * @author sameb@google.com (Sam Berlin) */ class LinkedServletBindingImpl extends AbstractServletModuleBinding> implements LinkedServletBinding { LinkedServletBindingImpl(Map initParams, String pattern, Key target, UriPatternMatcher patternMatcher) { super(initParams, pattern, target, patternMatcher); } public Key getLinkedKey() { return getTarget(); } @Override public String toString() { return new ToStringBuilder(LinkedServletBinding.class) .add("pattern", getPattern()) .add("initParams", getInitParams()) .add("uriPatternType", getUriPatternType()) .add("linkedServletKey", getLinkedKey()) .toString(); } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java0000644000175000017500000002341411475262552027471 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Key; import com.google.inject.OutOfScopeException; import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.internal.util.Maps; import com.google.inject.internal.util.Preconditions; import java.util.Map; import java.util.concurrent.Callable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * Servlet scopes. * * @author crazybob@google.com (Bob Lee) */ public class ServletScopes { private ServletScopes() {} /** A sentinel attribute value representing null. */ enum NullObject { INSTANCE } /** * HTTP servlet request scope. */ public static final Scope REQUEST = new Scope() { public Provider scope(Key key, final Provider creator) { final String name = key.toString(); return new Provider() { public T get() { // Check if the alternate request scope should be used, if no HTTP // request is in progress. if (null == GuiceFilter.localContext.get()) { // NOTE(dhanji): We don't need to synchronize on the scope map // unlike the HTTP request because we're the only ones who have // a reference to it, and it is only available via a threadlocal. Map scopeMap = requestScopeContext.get(); if (null != scopeMap) { @SuppressWarnings("unchecked") T t = (T) scopeMap.get(name); // Accounts for @Nullable providers. if (NullObject.INSTANCE == t) { return null; } if (t == null) { t = creator.get(); // Store a sentinel for provider-given null values. scopeMap.put(name, t != null ? t : NullObject.INSTANCE); } return t; } // else: fall into normal HTTP request scope and out of scope // exception is thrown. } HttpServletRequest request = GuiceFilter.getRequest(); synchronized (request) { Object obj = request.getAttribute(name); if (NullObject.INSTANCE == obj) { return null; } @SuppressWarnings("unchecked") T t = (T) obj; if (t == null) { t = creator.get(); request.setAttribute(name, (t != null) ? t : NullObject.INSTANCE); } return t; } } public String toString() { return String.format("%s[%s]", creator, REQUEST); } }; } public String toString() { return "ServletScopes.REQUEST"; } }; /** * HTTP session scope. */ public static final Scope SESSION = new Scope() { public Provider scope(Key key, final Provider creator) { final String name = key.toString(); return new Provider() { public T get() { HttpSession session = GuiceFilter.getRequest().getSession(); synchronized (session) { Object obj = session.getAttribute(name); if (NullObject.INSTANCE == obj) { return null; } @SuppressWarnings("unchecked") T t = (T) obj; if (t == null) { t = creator.get(); session.setAttribute(name, (t != null) ? t : NullObject.INSTANCE); } return t; } } public String toString() { return String.format("%s[%s]", creator, SESSION); } }; } public String toString() { return "ServletScopes.SESSION"; } }; /** * Wraps the given callable in a contextual callable that "continues" the * HTTP request in another thread. This acts as a way of transporting * request context data from the request processing thread to to worker * threads. *

* There are some limitations: *

    *
  • Derived objects (i.e. anything marked @RequestScoped will not be * transported.
  • *
  • State changes to the HttpServletRequest after this method is called * will not be seen in the continued thread.
  • *
  • Only the HttpServletRequest, ServletContext and request parameter * map are available in the continued thread. The response and session * are not available.
  • *
* * @param callable code to be executed in another thread, which depends on * the request scope. * @param seedMap the initial set of scoped instances for Guice to seed the * request scope with. To seed a key with null, use {@code null} as * the value. * @return a callable that will invoke the given callable, making the request * context available to it. * @throws OutOfScopeException if this method is called from a non-request * thread, or if the request has completed. * * @since 3.0 */ public static Callable continueRequest(final Callable callable, final Map, Object> seedMap) { Preconditions.checkArgument(null != seedMap, "Seed map cannot be null, try passing in Collections.emptyMap() instead."); // Snapshot the seed map and add all the instances to our continuing HTTP request. final ContinuingHttpServletRequest continuingRequest = new ContinuingHttpServletRequest(GuiceFilter.getRequest()); for (Map.Entry, Object> entry : seedMap.entrySet()) { Object value = validateAndCanonicalizeValue(entry.getKey(), entry.getValue()); continuingRequest.setAttribute(entry.getKey().toString(), value); } return new Callable() { private HttpServletRequest request = continuingRequest; public T call() throws Exception { GuiceFilter.Context context = GuiceFilter.localContext.get(); Preconditions.checkState(null == context, "Cannot continue request in the same thread as a HTTP request!"); // Only set up the request continuation if we're running in a // new vanilla thread. GuiceFilter.localContext.set(new GuiceFilter.Context(request, null)); try { return callable.call(); } finally { // Clear the copied context if we set one up. if (null == context) { GuiceFilter.localContext.remove(); } } } }; } /** * A threadlocal scope map for non-http request scopes. The {@link #REQUEST} * scope falls back to this scope map if no http request is available, and * requires {@link #scopeRequest} to be called as an alertnative. */ private static final ThreadLocal> requestScopeContext = new ThreadLocal>(); /** * Scopes the given callable inside a request scope. This is not the same * as the HTTP request scope, but is used if no HTTP request scope is in * progress. In this way, keys can be scoped as @RequestScoped and exist * in non-HTTP requests (for example: RPC requests) as well as in HTTP * request threads. * * @param callable code to be executed which depends on the request scope. * Typically in another thread, but not necessarily so. * @param seedMap the initial set of scoped instances for Guice to seed the * request scope with. To seed a key with null, use {@code null} as * the value. * @return a callable that when called will run inside the a request scope * that exposes the instances in the {@code seedMap} as scoped keys. * @since 3.0 */ public static Callable scopeRequest(final Callable callable, Map, Object> seedMap) { Preconditions.checkArgument(null != seedMap, "Seed map cannot be null, try passing in Collections.emptyMap() instead."); // Copy the seed values into our local scope map. final Map scopeMap = Maps.newHashMap(); for (Map.Entry, Object> entry : seedMap.entrySet()) { Object value = validateAndCanonicalizeValue(entry.getKey(), entry.getValue()); scopeMap.put(entry.getKey().toString(), value); } return new Callable() { public T call() throws Exception { Preconditions.checkState(null == GuiceFilter.localContext.get(), "An HTTP request is already in progress, cannot scope a new request in this thread."); Preconditions.checkState(null == requestScopeContext.get(), "A request scope is already in progress, cannot scope a new request in this thread."); requestScopeContext.set(scopeMap); try { return callable.call(); } finally { requestScopeContext.remove(); } } }; } /** * Validates the key and object, ensuring the value matches the key type, and * canonicalizing null objects to the null sentinel. */ private static Object validateAndCanonicalizeValue(Key key, Object object) { if (object == null || object == NullObject.INSTANCE) { return NullObject.INSTANCE; } if (!key.getTypeLiteral().getRawType().isInstance(object)) { throw new IllegalArgumentException("Value[" + object + "] of type[" + object.getClass().getName() + "] is not compatible with key[" + key + "]"); } return object; } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/AbstractServletModuleBinding.java0000644000175000017500000000324011467443616032437 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.util.Map; /** * Abstract implementation for all servlet module bindings * * @author sameb@google.com (Sam Berlin) */ class AbstractServletModuleBinding implements ServletModuleBinding { private final Map initParams; private final String pattern; private final T target; private final UriPatternMatcher patternMatcher; AbstractServletModuleBinding(Map initParams, String pattern, T target, UriPatternMatcher patternMatcher) { this.initParams = initParams; this.pattern = pattern; this.target = target; this.patternMatcher = patternMatcher; } public Map getInitParams() { return initParams; } public String getPattern() { return pattern; } protected T getTarget() { return target; } public UriPatternType getUriPatternType() { return patternMatcher.getPatternType(); } public boolean matchesUri(String uri) { return patternMatcher.matches(uri); } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/DefaultFilterPipeline.java0000644000175000017500000000271311434007752031101 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.Singleton; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * This default pipeline simply dispatches to web.xml's servlet pipeline. * * @author dhanji@gmail.com (Dhanji R. Prasanna) * @see com.google.inject.servlet.ManagedFilterPipeline See Also ManagedFilterPipeline. */ @Singleton class DefaultFilterPipeline implements FilterPipeline { public void initPipeline(ServletContext context) { } public void destroyPipeline() { } public void dispatch(ServletRequest request, ServletResponse response, FilterChain proceedingFilterChain) throws IOException, ServletException { proceedingFilterChain.doFilter(request, response); } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/ContinuingHttpServletRequest.java0000644000175000017500000000450611445101174032551 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import com.google.inject.OutOfScopeException; import com.google.inject.internal.util.Maps; import java.io.IOException; import java.util.Map; import javax.servlet.ServletInputStream; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpSession; /** * A wrapper for requests that makes requests immutable, taking a snapshot * of the original request. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ class ContinuingHttpServletRequest extends HttpServletRequestWrapper { // We clear out the attributes as they are mutable and not thread-safe. private final Map attributes = Maps.newHashMap(); public ContinuingHttpServletRequest(HttpServletRequest request) { super(request); } @Override public HttpSession getSession() { throw new OutOfScopeException("Cannot access the session in a continued request"); } @Override public HttpSession getSession(boolean create) { throw new UnsupportedOperationException("Cannot access the session in a continued request"); } @Override public ServletInputStream getInputStream() throws IOException { throw new UnsupportedOperationException("Cannot access raw request on a continued request"); } @Override public void setAttribute(String name, Object o) { attributes.put(name, o); } @Override public void removeAttribute(String name) { attributes.remove(name); } @Override public Object getAttribute(String name) { return attributes.get(name); } @Override public Cookie[] getCookies() { // TODO(dhanji): Cookies themselves are mutable. Is this a problem? return super.getCookies().clone(); } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java0000644000175000017500000000475411434007752031112 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * A Filter chain impl which basically passes itself to the "current" filter and iterates the chain * on {@code doFilter()}. Modeled on something similar in Apache Tomcat. * * Following this, it attempts to dispatch to guice-servlet's registered servlets using the * ManagedServletPipeline. * * And the end, it proceeds to the web.xml (default) servlet filter chain, if needed. * * @author Dhanji R. Prasanna * @since 1.0 */ class FilterChainInvocation implements FilterChain { private final FilterDefinition[] filterDefinitions; private final FilterChain proceedingChain; private final ManagedServletPipeline servletPipeline; //state variable tracks current link in filterchain private int index = -1; public FilterChainInvocation(FilterDefinition[] filterDefinitions, ManagedServletPipeline servletPipeline, FilterChain proceedingChain) { this.filterDefinitions = filterDefinitions; this.servletPipeline = servletPipeline; this.proceedingChain = proceedingChain; } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { index++; //dispatch down the chain while there are more filters if (index < filterDefinitions.length) { filterDefinitions[index].doFilter(servletRequest, servletResponse, this); } else { //we've reached the end of the filterchain, let's try to dispatch to a servlet final boolean serviced = servletPipeline.service(servletRequest, servletResponse); //dispatch to the normal filter chain only if one of our servlets did not match if (!serviced) { proceedingChain.doFilter(servletRequest, servletResponse); } } } } guice-3.0/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java0000644000175000017500000000314111434212566030257 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; /** * A general interface for matching a URI against a URI pattern. Guice-servlet provides regex and * servlet-style pattern matching out of the box. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ interface UriPatternMatcher { /** * @param uri A "contextual" (i.e. relative) Request URI, *not* a complete one. * @return Returns true if the uri matches the pattern. */ boolean matches(String uri); /** * @param pattern The Path that this service pattern can match against. * @return Returns a canonical servlet path from this pattern. For instance, if the pattern is * {@code /home/*} then the path extracted will be {@code /home}. Each pattern matcher * implementation must decide and publish what a canonical path represents. * * NOTE(dhanji): This method returns null for the regex pattern matcher. */ String extractPath(String pattern); /** Returns the type of pattern this is. */ UriPatternType getPatternType(); } guice-3.0/extensions/servlet/src/com/google/inject/servlet/InstanceServletBinding.java0000644000175000017500000000171711467443322031273 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.servlet; import javax.servlet.http.HttpServlet; /** * A binding to a single instance of a servlet. * * @author sameb@google.com * @since 3.0 */ public interface InstanceServletBinding extends ServletModuleBinding { /** Returns the servlet instance that will be used. */ HttpServlet getServletInstance(); } guice-3.0/extensions/servlet/servlet.iml0000644000175000017500000000244411434007750020423 0ustar drazzibdrazzib guice-3.0/extensions/assistedinject/0000755000175000017500000000000011542727752017573 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/build/0000755000175000017500000000000011542727752020672 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/build/META-INF/0000755000175000017500000000000011542727752022032 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/build/META-INF/MANIFEST.MF0000644000175000017500000000126411542727750023465 0ustar drazzibdrazzibManifest-Version: 1.0 Export-Package: com.google.inject.assistedinject;version="1.3" Bundle-Name: guice-assistedinject Created-By: 1.6.0_23 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-Copyright: Copyright (C) 2006 Google Inc. Bundle-Vendor: Google, Inc. Fragment-Host: com.google.inject Bundle-Version: 3.0 Bundle-ManifestVersion: 2 Bundle-Description: Guice is a lightweight dependency injection framew ork for Java 5 and above Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-DocURL: http://code.google.com/p/google-guice/ Bundle-SymbolicName: com.google.inject.assistedinject Import-Package: javax.inject guice-3.0/extensions/assistedinject/build/dist/0000755000175000017500000000000011542727752021635 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/build/classes/0000755000175000017500000000000011542727752022327 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/build/classes/com/0000755000175000017500000000000011542727752023105 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/build/classes/com/google/0000755000175000017500000000000011542727752024361 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/build/classes/com/google/inject/0000755000175000017500000000000011542727752025635 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/build/classes/com/google/inject/assistedinject/0000755000175000017500000000000011542727752030651 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/assistedinject.iml0000644000175000017500000000147011214265014023274 0ustar drazzibdrazzib guice-3.0/extensions/assistedinject/pom.xml0000644000175000017500000000107611463234200021073 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-assistedinject Google Guice - Extensions - AssistedInject guice-3.0/extensions/assistedinject/build.xml0000644000175000017500000000125111461750560021404 0ustar drazzibdrazzib guice-3.0/extensions/assistedinject/build.properties0000644000175000017500000000026211461376774023014 0ustar drazzibdrazziblib.dir=../../lib src.dir=src test.dir=test build.dir=build test.class=com.google.inject.assistedinject.FactoryProviderTest module=com.google.inject.assistedinject fragment=true guice-3.0/extensions/assistedinject/test/0000755000175000017500000000000011214265012020530 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/test/com/0000755000175000017500000000000011214265012021306 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/test/com/google/0000755000175000017500000000000011214265012022562 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/test/com/google/inject/0000755000175000017500000000000011214265012024036 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/test/com/google/inject/assistedinject/0000755000175000017500000000000011456371576027077 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/test/com/google/inject/assistedinject/ManyConstructorsTest.java0000644000175000017500000002055311353420722034124 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import junit.framework.TestCase; import com.google.inject.AbstractModule; import com.google.inject.Asserts; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; /** * @author sameb@google.com (Sam Berlin) */ public class ManyConstructorsTest extends TestCase { public void testTwoConstructors() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(Factory.class)); } }); Factory factory = injector.getInstance(Factory.class); Foo noIndex = factory.create("no index"); assertEquals("no index", noIndex.name); assertEquals(null, noIndex.index); Foo index = factory.create("index", 1); assertEquals("index", index.name); assertEquals(1, index.index.intValue()); } public void testDifferentOrderParameters() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(OtherFactory.class)); } }); OtherFactory factory = injector.getInstance(OtherFactory.class); Foo noIndex = factory.create("no index"); assertEquals("no index", noIndex.name); assertEquals(null, noIndex.index); Foo index = factory.create(1, "index"); assertEquals("index", index.name); assertEquals(1, index.index.intValue()); Foo index2 = factory.create("index", 2); assertEquals("index", index2.name); assertEquals(2, index2.index.intValue()); } public void testInterfaceToImpl() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder() .implement(Bar.class, Foo.class) .build(BarFactory.class)); } }); BarFactory factory = injector.getInstance(BarFactory.class); Bar noIndex = factory.create("no index"); assertEquals("no index", noIndex.getName()); assertEquals(null, noIndex.getIndex()); Bar index = factory.create("index", 1); assertEquals("index", index.getName()); assertEquals(1, index.getIndex().intValue()); } public void testUsingOneConstructor() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(SimpleFactory.class)); } }); SimpleFactory factory = injector.getInstance(SimpleFactory.class); Foo noIndex = factory.create("no index"); assertEquals("no index", noIndex.name); assertEquals(null, noIndex.index); injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(SimpleFactory2.class)); } }); SimpleFactory2 factory2 = injector.getInstance(SimpleFactory2.class); Foo index = factory2.create("index", 1); assertEquals("index", index.name); assertEquals(1, index.index.intValue()); } public void testTooManyMatchingConstructors() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder() .implement(Foo.class, TooManyMatches.class) .build(SimpleFactory2.class)); } }); fail("should have failed"); } catch (CreationException expected) { Asserts.assertContains(expected.getMessage(), "1) " + TooManyMatches.class.getName() + " has more than one constructor annotated with @AssistedInject that " + "matches the parameters in method " + SimpleFactory2.class.getName()); } } public void testNoMatchingConstructorsBecauseTooManyParams() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(ComplexFactory.class)); } }); fail("should have failed"); } catch (CreationException expected) { Asserts.assertContains(expected.getMessage(), "1) " + Foo.class.getName() + " has @AssistedInject constructors, but none of them match the parameters in method " + ComplexFactory.class.getName()); } } public void testNoMatchingConstrucotsBecauseTooLittleParams() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(NullFactory.class)); } }); fail("should have failed"); } catch (CreationException expected) { Asserts.assertContains(expected.getMessage(), "1) " + Foo.class.getName() + " has @AssistedInject constructors, but none of them match the parameters in method " + NullFactory.class.getName()); } } public static interface ComplexFactory { Foo create(String name, int idx, float weight); } public static interface NullFactory { Foo create(); } public static interface OtherFactory { Foo create(String name, int idx); Foo create(int idx, String name); Foo create(String name); } public static interface Factory { Foo create(String name); Foo create(String name, int idx); } public static interface BarFactory { Bar create(String name); Bar create(String name, int idx); } public static interface SimpleFactory { Foo create(String name); } public static interface SimpleFactory2 { Foo create(String name, int idx); } public static class TooManyMatches extends Foo { @AssistedInject TooManyMatches(@Assisted String name, @Assisted int index) { } @AssistedInject TooManyMatches(@Assisted int index, @Assisted String name) { } } public static class Foo implements Bar { private String name; private Integer index; Foo() {} @AssistedInject Foo(@Assisted String name) { this.name = name; this.index = null; } @AssistedInject Foo(@Assisted String name, @Assisted int index) { this.name = name; this.index = index; } Foo(String a, String b, String c) { } public String getName() { return name; } public Integer getIndex() { return index; } } public static interface Bar { String getName(); Integer getIndex(); } public void testDependenciesAndOtherAnnotations() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(FamilyFarmFactory.class)); } }); FamilyFarmFactory factory = injector.getInstance(FamilyFarmFactory.class); Farm pops = factory.popsFarm("Pop"); assertEquals("Pop", pops.pop); assertEquals(null, pops.mom); Farm moms = factory.momsFarm("Mom"); assertEquals(null, moms.pop); assertEquals("Mom", moms.mom); Farm momAndPop = factory.momAndPopsFarm("Mom", "Pop"); assertEquals("Pop", momAndPop.pop); assertEquals("Mom", momAndPop.mom); } public static interface FamilyFarmFactory { Farm popsFarm(String pop); Farm momsFarm(@Assisted("mom") String mom); Farm momAndPopsFarm(@Assisted("mom") String mom, @Assisted("pop") String pop); } public static class Farm { String pop; String mom; @AssistedInject Farm(@Assisted String pop, Dog dog) { this.pop = pop; } @AssistedInject Farm(@Assisted("mom") String mom, @Assisted("pop") String pop, Cow cow, Dog dog) { this.pop = pop; this.mom = mom; } @AssistedInject Farm(@Assisted("mom") String mom, Cow cow) { this.mom = mom; } } public static class Cow {} public static class Dog {} }guice-3.0/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProviderTest.java0000644000175000017500000006403011413604604033707 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.AbstractModule; import static com.google.inject.Asserts.assertContains; import com.google.inject.Binding; import com.google.inject.ConfigurationException; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import java.awt.Color; import java.util.Collection; import java.util.Collections; import java.util.Set; import junit.framework.TestCase; /** * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) */ public class FactoryProviderTest extends TestCase { public void testAssistedFactory() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); bind(ColoredCarFactory.class) .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE); assertEquals(Color.BLUE, blueMustang.color); assertEquals(5.0d, blueMustang.engineSize); Mustang redMustang = (Mustang) carFactory.create(Color.RED); assertEquals(Color.RED, redMustang.color); assertEquals(5.0d, redMustang.engineSize); } public void testFactoryBindingDependencies() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); bind(ColoredCarFactory.class) .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); } }); Binding binding = injector.getBinding(ColoredCarFactory.class); HasDependencies hasDependencies = (HasDependencies) binding; assertEquals(ImmutableSet.>of(Dependency.get(Key.get(double.class))), hasDependencies.getDependencies()); } public void testAssistedFactoryWithAnnotations() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); bind(ColoredCarFactory.class) .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Camaro.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Camaro blueCamaro = (Camaro) carFactory.create(Color.BLUE); assertEquals(Color.BLUE, blueCamaro.color); assertEquals(1984, blueCamaro.modelYear); assertEquals(250, blueCamaro.horsePower); Camaro redCamaro = (Camaro) carFactory.create(Color.RED); assertEquals(Color.RED, redCamaro.color); assertEquals(1984, redCamaro.modelYear); assertEquals(250, redCamaro.horsePower); } interface Car { } interface ColoredCarFactory { Car create(Color color); } public static class Mustang implements Car { private final double engineSize; private final Color color; @AssistedInject public Mustang(double engineSize, @Assisted Color color) { this.engineSize = engineSize; this.color = color; } } public static class Camaro implements Car { private final int horsePower; private final int modelYear; private final Color color; @AssistedInject public Camaro( @Named("horsePower")int horsePower, @Named("modelYear")int modelYear, @Assisted Color color) { this.horsePower = horsePower; this.modelYear = modelYear; this.color = color; } } interface SummerCarFactory { Car create(Color color, boolean convertable); Car createConvertible(Color color); } public void testFactoryWithMultipleMethods() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(float.class).toInstance(140f); bind(SummerCarFactory.class).toProvider( FactoryProvider.newFactory(SummerCarFactory.class, Corvette.class)); } }); SummerCarFactory carFactory = injector.getInstance(SummerCarFactory.class); Corvette blueCorvette = (Corvette) carFactory.createConvertible(Color.BLUE); assertEquals(Color.BLUE, blueCorvette.color); assertEquals(100f, blueCorvette.maxMph); assertTrue(blueCorvette.isConvertable); Corvette redCorvette = (Corvette) carFactory.create(Color.RED, false); assertEquals(Color.RED, redCorvette.color); assertEquals(140f, redCorvette.maxMph); assertFalse(redCorvette.isConvertable); } public static class Corvette implements Car { private boolean isConvertable; private Color color; private float maxMph; @AssistedInject public Corvette(@Assisted Color color) { this(color, 100f, true); } public Corvette(@Assisted Color color, @Assisted boolean isConvertable) { throw new IllegalStateException("Not an @AssistedInject constructor"); } @AssistedInject public Corvette(@Assisted Color color, Float maxMph, @Assisted boolean isConvertable) { this.isConvertable = isConvertable; this.color = color; this.maxMph = maxMph; } } public void testFactoryMethodsMismatch() { try { FactoryProvider.newFactory(SummerCarFactory.class, Beetle.class); fail(); } catch(ConfigurationException e) { assertContains(e.getMessage(), "Constructor mismatch"); } } public static class Beetle implements Car { @AssistedInject public Beetle(@Assisted Color color) { throw new IllegalStateException("Conflicting constructors"); } @AssistedInject public Beetle(@Assisted Color color, @Assisted boolean isConvertable) { throw new IllegalStateException("Conflicting constructors"); } @AssistedInject public Beetle(@Assisted Color color, @Assisted boolean isConvertable, float maxMph) { throw new IllegalStateException("Conflicting constructors"); } } public void testMethodsAndFieldsGetInjected() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("turbo"); bind(int.class).toInstance(911); bind(double.class).toInstance(50000d); bind(ColoredCarFactory.class) .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Porshe.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Porshe grayPorshe = (Porshe) carFactory.create(Color.GRAY); assertEquals(Color.GRAY, grayPorshe.color); assertEquals(50000d, grayPorshe.price); assertEquals(911, grayPorshe.model); assertEquals("turbo", grayPorshe.name); } public static class Porshe implements Car { private final Color color; private final double price; private @Inject String name; private int model; @AssistedInject public Porshe(@Assisted Color color, double price) { this.color = color; this.price = price; } @Inject void setModel(int model) { this.model = model; } } public void testProviderInjection() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("trans am"); bind(ColoredCarFactory.class) .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Firebird.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Firebird blackFirebird = (Firebird) carFactory.create(Color.BLACK); assertEquals(Color.BLACK, blackFirebird.color); assertEquals("trans am", blackFirebird.modifiersProvider.get()); } public static class Firebird implements Car { private final Provider modifiersProvider; private final Color color; @AssistedInject public Firebird(Provider modifiersProvider, @Assisted Color color) { this.modifiersProvider = modifiersProvider; this.color = color; } } public void testTypeTokenInjection() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(new TypeLiteral>() {}).toInstance(Collections.singleton("Flux Capacitor")); bind(new TypeLiteral>() {}).toInstance(Collections.singleton(88)); bind(ColoredCarFactory.class) .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, DeLorean.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); DeLorean deLorean = (DeLorean) carFactory.create(Color.GRAY); assertEquals(Color.GRAY, deLorean.color); assertEquals("Flux Capacitor", deLorean.features.iterator().next()); assertEquals(new Integer(88), deLorean.featureActivationSpeeds.iterator().next()); } public static class DeLorean implements Car { private final Set features; private final Set featureActivationSpeeds; private final Color color; @AssistedInject public DeLorean( Set extraFeatures, Set featureActivationSpeeds, @Assisted Color color) { this.features = extraFeatures; this.featureActivationSpeeds = featureActivationSpeeds; this.color = color; } } public void testTypeTokenProviderInjection() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(new TypeLiteral>() { }).toInstance(Collections.singleton("Datsun")); bind(ColoredCarFactory.class) .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Z.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Z orangeZ = (Z) carFactory.create(Color.ORANGE); assertEquals(Color.ORANGE, orangeZ.color); assertEquals("Datsun", orangeZ.manufacturersProvider.get().iterator().next()); } public static class Z implements Car { private final Provider> manufacturersProvider; private final Color color; @AssistedInject public Z(Provider> manufacturersProvider, @Assisted Color color) { this.manufacturersProvider = manufacturersProvider; this.color = color; } } public static class Prius implements Car { @SuppressWarnings("unused") private final Color color; @AssistedInject private Prius(@Assisted Color color) { this.color = color; } } public void testAssistInjectionInNonPublicConstructor() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class) .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Prius.class)); } }); Car car = injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE); } public static class ExplodingCar implements Car { @AssistedInject public ExplodingCar(@Assisted Color color) { throw new IllegalStateException("kaboom!"); } } public void testExceptionDuringConstruction() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, ExplodingCar.class)); } }); try { injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE); fail(); } catch (IllegalStateException e) { assertEquals("kaboom!", e.getMessage()); } } public static class DefectiveCar implements Car { @AssistedInject public DefectiveCar() throws ExplosionException, FireException { throw new ExplosionException(); } } public static class ExplosionException extends Exception { } public static class FireException extends Exception { } public interface DefectiveCarFactoryWithNoExceptions { Car createCar(); } public interface DefectiveCarFactory { Car createCar() throws FireException; } public void testFactoryMethodMustDeclareAllConstructorExceptions() { try { FactoryProvider.newFactory(DefectiveCarFactoryWithNoExceptions.class, DefectiveCar.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "no compatible exception is thrown"); } } public interface CorrectDefectiveCarFactory { Car createCar() throws FireException, ExplosionException; } public void testConstructorExceptionsAreThrownByFactory() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(CorrectDefectiveCarFactory.class).toProvider( FactoryProvider.newFactory( CorrectDefectiveCarFactory.class, DefectiveCar.class)); } }); try { injector.getInstance(CorrectDefectiveCarFactory.class).createCar(); fail(); } catch (FireException e) { fail(); } catch (ExplosionException expected) { } } public static class MultipleConstructorDefectiveCar implements Car { @AssistedInject public MultipleConstructorDefectiveCar() throws ExplosionException { throw new ExplosionException(); } @AssistedInject public MultipleConstructorDefectiveCar(@Assisted Color c) throws FireException { throw new FireException(); } } public interface MultipleConstructorDefectiveCarFactory { Car createCar() throws ExplosionException; Car createCar(Color r) throws FireException; } public void testMultipleConstructorExceptionMatching() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(MultipleConstructorDefectiveCarFactory.class).toProvider( FactoryProvider.newFactory( MultipleConstructorDefectiveCarFactory.class, MultipleConstructorDefectiveCar.class)); } }); MultipleConstructorDefectiveCarFactory factory = injector.getInstance(MultipleConstructorDefectiveCarFactory.class); try { factory.createCar(); fail(); } catch (ExplosionException expected) { } try { factory.createCar(Color.RED); fail(); } catch (FireException expected) { } } public static class WildcardCollection { public interface Factory { WildcardCollection create(Collection items); } @AssistedInject public WildcardCollection(@Assisted Collection items) { } } public void testWildcardGenerics() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(WildcardCollection.Factory.class).toProvider( FactoryProvider.newFactory( WildcardCollection.Factory.class, WildcardCollection.class)); } }); WildcardCollection.Factory factory = injector.getInstance(WildcardCollection.Factory.class); factory.create(Collections.emptyList()); } public static class SteeringWheel {} public static class Fiat implements Car { @SuppressWarnings("unused") private final SteeringWheel steeringWheel; @SuppressWarnings("unused") private final Color color; @AssistedInject public Fiat(SteeringWheel steeringWheel, @Assisted Color color) { this.steeringWheel = steeringWheel; this.color = color; } } public void testFactoryWithImplicitBindings() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory( ColoredCarFactory.class, Fiat.class)); } }); ColoredCarFactory coloredCarFactory = injector.getInstance(ColoredCarFactory.class); Fiat fiat = (Fiat) coloredCarFactory.create(Color.GREEN); assertEquals(Color.GREEN, fiat.color); assertNotNull(fiat.steeringWheel); } public void testFactoryFailsWithMissingBinding() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class) .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Parameter of type 'double' is not injectable or annotated with @Assisted"); } } public void testMethodsDeclaredInObject() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); bind(ColoredCarFactory.class) .toProvider(FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); carFactory.equals(carFactory); carFactory.hashCode(); carFactory.toString(); } public void testAssistedInjectConstructorAndAssistedFactoryParameterMustNotMix() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); bind(AssistedParamsFactory.class) .toProvider(FactoryProvider.newFactory(AssistedParamsFactory.class, Mustang.class)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "Factory method " + AssistedParamsFactory.class.getName() + ".create() has an @Assisted parameter, which " + "is incompatible with the deprecated @AssistedInject annotation."); } } interface AssistedParamsFactory { Car create(@Assisted Color color); } interface GenericColoredCarFactory { T create(Color color); } public void testGenericAssistedFactory() { final TypeLiteral> mustangTypeLiteral = new TypeLiteral>() {}; final TypeLiteral> camaroTypeLiteral = new TypeLiteral>() {}; Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); bind(mustangTypeLiteral).toProvider( FactoryProvider.newFactory(mustangTypeLiteral, TypeLiteral.get(Mustang.class))); bind(camaroTypeLiteral).toProvider( FactoryProvider.newFactory(camaroTypeLiteral, TypeLiteral.get(Camaro.class))); } }); GenericColoredCarFactory mustangFactory = injector.getInstance(Key.get(mustangTypeLiteral)); GenericColoredCarFactory camaroFactory = injector.getInstance(Key.get(camaroTypeLiteral)); Mustang blueMustang = mustangFactory.create(Color.BLUE); assertEquals(Color.BLUE, blueMustang.color); assertEquals(5.0d, blueMustang.engineSize); Camaro redCamaro = camaroFactory.create(Color.RED); assertEquals(Color.RED, redCamaro.color); assertEquals(1984, redCamaro.modelYear); assertEquals(250, redCamaro.horsePower); } public interface Insurance { } public static class MustangInsurance implements Insurance { private final double premium; private final double limit; private Mustang car; @AssistedInject public MustangInsurance(@Named("lowLimit") double limit, @Assisted Mustang car, @Assisted double premium) { this.premium = premium; this.limit = limit; this.car = car; } public void sell() {} } public static class CamaroInsurance implements Insurance { private final double premium; private final double limit; private Camaro car; @AssistedInject public CamaroInsurance(@Named("highLimit") double limit, @Assisted Camaro car, @Assisted double premium) { this.premium = premium; this.limit = limit; this.car = car; } public void sell() {} } public interface MustangInsuranceFactory { public Insurance create(Mustang car, double premium); } public interface CamaroInsuranceFactory { public Insurance create(Camaro car, double premium); } public void testAssistedFactoryForConcreteType() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d); bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d); bind(MustangInsuranceFactory.class).toProvider( FactoryProvider.newFactory(MustangInsuranceFactory.class, MustangInsurance.class)); bind(CamaroInsuranceFactory.class).toProvider( FactoryProvider.newFactory(CamaroInsuranceFactory.class, CamaroInsurance.class)); } }); MustangInsuranceFactory mustangInsuranceFactory = injector.getInstance(MustangInsuranceFactory.class); CamaroInsuranceFactory camaroInsuranceFactory = injector.getInstance(CamaroInsuranceFactory.class); Mustang mustang = new Mustang(5000d, Color.BLACK); MustangInsurance mustangPolicy = (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d); assertEquals(800.0d, mustangPolicy.premium); assertEquals(50000.0d, mustangPolicy.limit); Camaro camaro = new Camaro(3000, 1967, Color.BLUE); CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d); assertEquals(800.0d, camaroPolicy.premium); assertEquals(100000.0d, camaroPolicy.limit); } public interface InsuranceFactory { public Insurance create(T car, double premium); } public void testAssistedFactoryForParameterizedType() { final TypeLiteral> mustangInsuranceFactoryType = new TypeLiteral>() {}; final TypeLiteral> camaroInsuranceFactoryType = new TypeLiteral>() {}; Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d); bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d); bind(mustangInsuranceFactoryType).toProvider(FactoryProvider.newFactory( mustangInsuranceFactoryType, TypeLiteral.get(MustangInsurance.class))); bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory( camaroInsuranceFactoryType, TypeLiteral.get(CamaroInsurance.class))); } }); InsuranceFactory mustangInsuranceFactory = injector.getInstance(Key.get(mustangInsuranceFactoryType)); InsuranceFactory camaroInsuranceFactory = injector.getInstance(Key.get(camaroInsuranceFactoryType)); Mustang mustang = new Mustang(5000d, Color.BLACK); MustangInsurance mustangPolicy = (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d); assertEquals(800.0d, mustangPolicy.premium); assertEquals(50000.0d, mustangPolicy.limit); Camaro camaro = new Camaro(3000, 1967, Color.BLUE); CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d); assertEquals(800.0d, camaroPolicy.premium); assertEquals(100000.0d, camaroPolicy.limit); } public static class AutoInsurance implements Insurance { private final double premium; private final double limit; private final T car; @AssistedInject public AutoInsurance(double limit, @Assisted T car, @Assisted double premium) { this.limit = limit; this.car = car; this.premium = premium; } public void sell() {} } public void testAssistedFactoryForTypeVariableParameters() { final TypeLiteral> camaroInsuranceFactoryType = new TypeLiteral>() {}; Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(50000.0d); bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory( camaroInsuranceFactoryType, new TypeLiteral>() {})); } }); InsuranceFactory camaroInsuranceFactory = injector.getInstance(Key.get(camaroInsuranceFactoryType)); Camaro camaro = new Camaro(3000, 1967, Color.BLUE); AutoInsurance camaroPolicy = (AutoInsurance) camaroInsuranceFactory.create(camaro, 800.0d); assertEquals(800.0d, camaroPolicy.premium); assertEquals(50000.0d, camaroPolicy.limit); assertEquals(camaro, camaroPolicy.car); } }guice-3.0/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProvider2Test.java0000644000175000017500000011070611461115054033772 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.AbstractModule; import static com.google.inject.Asserts.assertContains; import static com.google.inject.Asserts.assertEqualsBothWays; import com.google.inject.ConfigurationException; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Stage; import com.google.inject.TypeLiteral; import com.google.inject.matcher.Matchers; import com.google.inject.name.Named; import com.google.inject.name.Names; import junit.framework.TestCase; import java.awt.*; import java.util.Collection; import java.util.Collections; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; @SuppressWarnings("deprecation") public class FactoryProvider2Test extends TestCase { public void testAssistedFactory() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE); assertEquals(Color.BLUE, blueMustang.color); assertEquals(5.0d, blueMustang.engineSize); Mustang redMustang = (Mustang) carFactory.create(Color.RED); assertEquals(Color.RED, redMustang.color); assertEquals(5.0d, redMustang.engineSize); } public void testAssistedFactoryWithAnnotations() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Camaro.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Camaro blueCamaro = (Camaro) carFactory.create(Color.BLUE); assertEquals(Color.BLUE, blueCamaro.color); assertEquals(1984, blueCamaro.modelYear); assertEquals(250, blueCamaro.horsePower); Camaro redCamaro = (Camaro) carFactory.create(Color.RED); assertEquals(Color.RED, redCamaro.color); assertEquals(1984, redCamaro.modelYear); assertEquals(250, redCamaro.horsePower); } public interface Car {} interface ColoredCarFactory { Car create(Color color); } public static class Mustang implements Car { private final double engineSize; private final Color color; @Inject public Mustang(double engineSize, @Assisted Color color) { this.engineSize = engineSize; this.color = color; } public void drive() {} } public static class Camaro implements Car { private final int horsePower; private final int modelYear; private final Color color; @Inject public Camaro( @Named("horsePower") int horsePower, @Named("modelYear") int modelYear, @Assisted Color color) { this.horsePower = horsePower; this.modelYear = modelYear; this.color = color; } } interface SummerCarFactory { Car create(Color color, boolean convertable); } public void testFactoryUsesInjectedConstructor() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(float.class).toInstance(140f); bind(SummerCarFactory.class).toProvider( FactoryProvider.newFactory(SummerCarFactory.class, Corvette.class)); } }); SummerCarFactory carFactory = injector.getInstance(SummerCarFactory.class); Corvette redCorvette = (Corvette) carFactory.create(Color.RED, false); assertEquals(Color.RED, redCorvette.color); assertEquals(140f, redCorvette.maxMph); assertFalse(redCorvette.isConvertable); } public static class Corvette implements Car { private boolean isConvertable; private Color color; private float maxMph; public Corvette(Color color, boolean isConvertable) { throw new IllegalStateException("Not an @AssistedInject constructor"); } @Inject public Corvette(@Assisted Color color, Float maxMph, @Assisted boolean isConvertable) { this.isConvertable = isConvertable; this.color = color; this.maxMph = maxMph; } } public void testConstructorDoesntNeedAllFactoryMethodArguments() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(SummerCarFactory.class).toProvider( FactoryProvider.newFactory(SummerCarFactory.class, Beetle.class)); } }); SummerCarFactory factory = injector.getInstance(SummerCarFactory.class); Beetle beetle = (Beetle) factory.create(Color.RED, true); assertSame(Color.RED, beetle.color); } public static class Beetle implements Car { private final Color color; @Inject public Beetle(@Assisted Color color) { this.color = color; } } public void testMethodsAndFieldsGetInjected() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("turbo"); bind(int.class).toInstance(911); bind(double.class).toInstance(50000d); bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Porsche.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Porsche grayPorsche = (Porsche) carFactory.create(Color.GRAY); assertEquals(Color.GRAY, grayPorsche.color); assertEquals(50000d, grayPorsche.price); assertEquals(911, grayPorsche.model); assertEquals("turbo", grayPorsche.name); } public static class Porsche implements Car { private final Color color; private final double price; private @Inject String name; private int model; @Inject public Porsche(@Assisted Color color, double price) { this.color = color; this.price = price; } @Inject void setModel(int model) { this.model = model; } } public void testProviderInjection() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("trans am"); bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Firebird.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Firebird blackFirebird = (Firebird) carFactory.create(Color.BLACK); assertEquals(Color.BLACK, blackFirebird.color); assertEquals("trans am", blackFirebird.modifiersProvider.get()); } public static class Firebird implements Car { private final Provider modifiersProvider; private final Color color; @Inject public Firebird(Provider modifiersProvider, @Assisted Color color) { this.modifiersProvider = modifiersProvider; this.color = color; } } public void testAssistedProviderInjection() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("trans am"); bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Flamingbird.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Flamingbird flamingbird = (Flamingbird) carFactory.create(Color.BLACK); assertEquals(Color.BLACK, flamingbird.colorProvider.get()); assertEquals("trans am", flamingbird.modifiersProvider.get()); Flamingbird flamingbird2 = (Flamingbird) carFactory.create(Color.RED); assertEquals(Color.RED, flamingbird2.colorProvider.get()); assertEquals("trans am", flamingbird2.modifiersProvider.get()); // Make sure the original flamingbird is black still. assertEquals(Color.BLACK, flamingbird.colorProvider.get()); } public static class Flamingbird implements Car { private final Provider modifiersProvider; private final Provider colorProvider; @Inject public Flamingbird(Provider modifiersProvider, @Assisted Provider colorProvider) { this.modifiersProvider = modifiersProvider; this.colorProvider = colorProvider; } } public void testTypeTokenInjection() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(new TypeLiteral>() {}).toInstance(Collections.singleton("Flux Capacitor")); bind(new TypeLiteral>() {}).toInstance(Collections.singleton(88)); bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, DeLorean.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); DeLorean deLorean = (DeLorean) carFactory.create(Color.GRAY); assertEquals(Color.GRAY, deLorean.color); assertEquals("Flux Capacitor", deLorean.features.iterator().next()); assertEquals(new Integer(88), deLorean.featureActivationSpeeds.iterator().next()); } public static class DeLorean implements Car { private final Set features; private final Set featureActivationSpeeds; private final Color color; @Inject public DeLorean( Set extraFeatures, Set featureActivationSpeeds, @Assisted Color color) { this.features = extraFeatures; this.featureActivationSpeeds = featureActivationSpeeds; this.color = color; } } public void testTypeTokenProviderInjection() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(new TypeLiteral>() { }).toInstance(Collections.singleton("Datsun")); bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Z.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Z orangeZ = (Z) carFactory.create(Color.ORANGE); assertEquals(Color.ORANGE, orangeZ.color); assertEquals("Datsun", orangeZ.manufacturersProvider.get().iterator().next()); } public static class Z implements Car { private final Provider> manufacturersProvider; private final Color color; @Inject public Z(Provider> manufacturersProvider, @Assisted Color color) { this.manufacturersProvider = manufacturersProvider; this.color = color; } } public static class Prius implements Car { final Color color; @Inject private Prius(@Assisted Color color) { this.color = color; } } public void testAssistInjectionInNonPublicConstructor() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Prius.class)); } }); Prius prius = (Prius) injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE); assertEquals(prius.color, Color.ORANGE); } public static class ExplodingCar implements Car { @Inject public ExplodingCar(@Assisted Color color) { throw new IllegalStateException("kaboom!"); } } public void testExceptionDuringConstruction() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, ExplodingCar.class)); } }); try { injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE); fail(); } catch (IllegalStateException e) { assertEquals("kaboom!", e.getMessage()); } } public static class DefectiveCar implements Car { @Inject public DefectiveCar() throws ExplosionException, FireException { throw new ExplosionException(); } } public static class ExplosionException extends Exception { } public static class FireException extends Exception { } public interface DefectiveCarFactoryWithNoExceptions { Car createCar(); } public interface DefectiveCarFactory { Car createCar() throws FireException; } public interface CorrectDefectiveCarFactory { Car createCar() throws FireException, ExplosionException; } public void testConstructorExceptionsAreThrownByFactory() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(CorrectDefectiveCarFactory.class).toProvider( FactoryProvider.newFactory(CorrectDefectiveCarFactory.class, DefectiveCar.class)); } }); try { injector.getInstance(CorrectDefectiveCarFactory.class).createCar(); fail(); } catch (FireException e) { fail(); } catch (ExplosionException expected) { } } public static class WildcardCollection { public interface Factory { WildcardCollection create(Collection items); } @Inject public WildcardCollection(@Assisted Collection items) { } } public void testWildcardGenerics() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(WildcardCollection.Factory.class).toProvider( FactoryProvider.newFactory(WildcardCollection.Factory.class, WildcardCollection.class)); } }); WildcardCollection.Factory factory = injector.getInstance(WildcardCollection.Factory.class); factory.create(Collections.emptyList()); } public static class SteeringWheel {} public static class Fiat implements Car { private final SteeringWheel steeringWheel; private final Color color; @Inject public Fiat(SteeringWheel steeringWheel, @Assisted Color color) { this.steeringWheel = steeringWheel; this.color = color; } } public void testFactoryWithImplicitBindings() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Fiat.class)); } }); ColoredCarFactory coloredCarFactory = injector.getInstance(ColoredCarFactory.class); Fiat fiat = (Fiat) coloredCarFactory.create(Color.GREEN); assertEquals(Color.GREEN, fiat.color); assertNotNull(fiat.steeringWheel); } public void testFactoryFailsWithMissingBinding() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "Could not find a suitable constructor in java.lang.Double.", "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java"); } } public void testFactoryFailsWithMissingBindingInToolStage() { try { Guice.createInjector(Stage.TOOL, new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "Could not find a suitable constructor in java.lang.Double.", "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java"); } } public void testMethodsDeclaredInObject() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); assertEqualsBothWays(carFactory, carFactory); } static class Subaru implements Car { @Inject @Assisted Provider colorProvider; } public void testInjectingProviderOfParameter() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Subaru subaru = (Subaru) carFactory.create(Color.RED); assertSame(Color.RED, subaru.colorProvider.get()); assertSame(Color.RED, subaru.colorProvider.get()); Subaru sedan = (Subaru) carFactory.create(Color.BLUE); assertSame(Color.BLUE, sedan.colorProvider.get()); assertSame(Color.BLUE, sedan.colorProvider.get()); // and make sure the subaru is still red assertSame(Color.RED, subaru.colorProvider.get()); } public void testInjectingNullParameter() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Subaru subaru = (Subaru) carFactory.create(null); assertNull(subaru.colorProvider.get()); assertNull(subaru.colorProvider.get()); } interface ProviderBasedColoredCarFactory { Car createCar(Provider colorProvider, Provider stringProvider); Mustang createMustang(@Assisted("color") Provider colorProvider); } public void testAssistedProviderIsDisallowed() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ProviderBasedColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ProviderBasedColoredCarFactory.class, Subaru.class)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) A Provider may not be a type in a factory method of an AssistedInject." + "\n Offending instance is parameter [1] with key" + " [com.google.inject.Provider] on method [" + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]", "2) A Provider may not be a type in a factory method of an AssistedInject." + "\n Offending instance is parameter [2] with key" + " [com.google.inject.Provider] on method [" + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]", "3) A Provider may not be a type in a factory method of an AssistedInject." + "\n Offending instance is parameter [1] with key" + " [com.google.inject.Provider" + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]" + " on method [" + ProviderBasedColoredCarFactory.class.getName() + ".createMustang()]" ); } } interface JavaxProviderBasedColoredCarFactory { Car createCar(javax.inject.Provider colorProvider, javax.inject.Provider stringProvider); Mustang createMustang(@Assisted("color") javax.inject.Provider colorProvider); } public void testAssistedJavaxProviderIsDisallowed() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(JavaxProviderBasedColoredCarFactory.class).toProvider( FactoryProvider.newFactory(JavaxProviderBasedColoredCarFactory.class, Subaru.class)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) A Provider may not be a type in a factory method of an AssistedInject." + "\n Offending instance is parameter [1] with key" + " [com.google.inject.Provider] on method [" + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]", "2) A Provider may not be a type in a factory method of an AssistedInject." + "\n Offending instance is parameter [2] with key" + " [com.google.inject.Provider] on method [" + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]", "3) A Provider may not be a type in a factory method of an AssistedInject." + "\n Offending instance is parameter [1] with key" + " [com.google.inject.Provider" + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]" + " on method [" + JavaxProviderBasedColoredCarFactory.class.getName() + ".createMustang()]" ); } } public void testFactoryUseBeforeInitialization() { ColoredCarFactory carFactory = FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class) .get(); try { carFactory.create(Color.RED); fail(); } catch (IllegalStateException expected) { assertContains(expected.getMessage(), "Factories.create() factories cannot be used until they're initialized by Guice."); } } interface MustangFactory { Mustang create(Color color); } public void testFactoryBuildingConcreteTypes() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(double.class).toInstance(5.0d); // note there is no 'thatMakes()' call here: bind(MustangFactory.class).toProvider( FactoryProvider.newFactory(MustangFactory.class, Mustang.class)); } }); MustangFactory factory = injector.getInstance(MustangFactory.class); Mustang mustang = factory.create(Color.RED); assertSame(Color.RED, mustang.color); assertEquals(5.0d, mustang.engineSize); } static class Fleet { @Inject Mustang mustang; @Inject Camaro camaro; } interface FleetFactory { Fleet createFleet(Color color); } public void testInjectDeepIntoConstructedObjects() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(double.class).toInstance(5.0d); bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); bind(FleetFactory.class).toProvider(FactoryProvider.newFactory(FleetFactory.class, Fleet.class)); } }); FleetFactory fleetFactory = injector.getInstance(FleetFactory.class); Fleet fleet = fleetFactory.createFleet(Color.RED); assertSame(Color.RED, fleet.mustang.color); assertEquals(5.0d, fleet.mustang.engineSize); assertSame(Color.RED, fleet.camaro.color); assertEquals(250, fleet.camaro.horsePower); assertEquals(1984, fleet.camaro.modelYear); } interface TwoToneCarFactory { Car create(@Assisted("paint") Color paint, @Assisted("fabric") Color fabric); } static class Maxima implements Car { @Inject @Assisted("paint") Color paint; @Inject @Assisted("fabric") Color fabric; } public void testDistinctKeys() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(TwoToneCarFactory.class).toProvider( FactoryProvider.newFactory(TwoToneCarFactory.class, Maxima.class)); } }); TwoToneCarFactory factory = injector.getInstance(TwoToneCarFactory.class); Maxima maxima = (Maxima) factory.create(Color.BLACK, Color.GRAY); assertSame(Color.BLACK, maxima.paint); assertSame(Color.GRAY, maxima.fabric); } interface DoubleToneCarFactory { Car create(@Assisted("paint") Color paint, @Assisted("paint") Color morePaint); } public void testDuplicateKeys() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(DoubleToneCarFactory.class).toProvider( FactoryProvider.newFactory(DoubleToneCarFactory.class, Maxima.class)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "A binding to java.awt.Color annotated with @" + Assisted.class.getName() + "(value=paint) was already configured at"); } } /*if[AOP]*/ public void testMethodInterceptorsOnAssistedTypes() { final AtomicInteger invocationCount = new AtomicInteger(); final org.aopalliance.intercept.MethodInterceptor interceptor = new org.aopalliance.intercept.MethodInterceptor() { public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) throws Throwable { invocationCount.incrementAndGet(); return methodInvocation.proceed(); } }; Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bindInterceptor(Matchers.any(), Matchers.any(), interceptor); bind(Double.class).toInstance(5.0d); bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); } }); ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class); Mustang mustang = (Mustang) factory.create(Color.GREEN); assertEquals(0, invocationCount.get()); mustang.drive(); assertEquals(1, invocationCount.get()); } /*end[AOP]*/ /** * Our factories aren't reusable across injectors. Although this behaviour isn't something we * like, I have a test case to make sure the error message is pretty. */ public void testFactoryReuseErrorMessageIsPretty() { final Provider factoryProvider = FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class); Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); bind(ColoredCarFactory.class).toProvider(factoryProvider); } }); try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); bind(ColoredCarFactory.class).toProvider(factoryProvider); } }); fail(); } catch(CreationException expected) { assertContains(expected.getMessage(), "Factories.create() factories may only be used in one Injector!"); } } public void testNonAssistedFactoryMethodParameter() { try { FactoryProvider.newFactory(NamedParameterFactory.class, Mustang.class); fail(); } catch(ConfigurationException expected) { assertContains(expected.getMessage(), "Only @Assisted is allowed for factory parameters, but found @" + Named.class.getName()); } } interface NamedParameterFactory { Car create(@Named("seats") int seats, double engineSize); } public void testDefaultAssistedAnnotation() throws NoSuchFieldException { Assisted plainAssisted = Subaru.class.getDeclaredField("colorProvider").getAnnotation(Assisted.class); assertEqualsBothWays(FactoryProvider2.DEFAULT_ANNOTATION, plainAssisted); assertEquals(FactoryProvider2.DEFAULT_ANNOTATION.toString(), plainAssisted.toString()); } interface GenericColoredCarFactory { T create(Color color); } public void testGenericAssistedFactory() { final TypeLiteral> mustangTypeLiteral = new TypeLiteral>() {}; final TypeLiteral> camaroTypeLiteral = new TypeLiteral>() {}; Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); bind(mustangTypeLiteral) .toProvider(FactoryProvider.newFactory(mustangTypeLiteral, TypeLiteral.get(Mustang.class))); bind(camaroTypeLiteral) .toProvider(FactoryProvider.newFactory(camaroTypeLiteral, TypeLiteral.get(Camaro.class))); } }); GenericColoredCarFactory mustangFactory = injector.getInstance(Key.get(mustangTypeLiteral)); GenericColoredCarFactory camaroFactory = injector.getInstance(Key.get(camaroTypeLiteral)); Mustang blueMustang = mustangFactory.create(Color.BLUE); assertEquals(Color.BLUE, blueMustang.color); assertEquals(5.0d, blueMustang.engineSize); Camaro redCamaro = camaroFactory.create(Color.RED); assertEquals(Color.RED, redCamaro.color); assertEquals(1984, redCamaro.modelYear); assertEquals(250, redCamaro.horsePower); } public interface Insurance { } public static class MustangInsurance implements Insurance { private final double premium; private final double limit; private Mustang car; @Inject public MustangInsurance(@Named("lowLimit") double limit, @Assisted Mustang car, @Assisted double premium) { this.premium = premium; this.limit = limit; this.car = car; } public void sell() {} } public static class CamaroInsurance implements Insurance { private final double premium; private final double limit; private Camaro car; @Inject public CamaroInsurance(@Named("highLimit") double limit, @Assisted Camaro car, @Assisted double premium) { this.premium = premium; this.limit = limit; this.car = car; } public void sell() {} } public interface MustangInsuranceFactory { public Insurance create(Mustang car, double premium); } public interface CamaroInsuranceFactory { public Insurance create(Camaro car, double premium); } public void testAssistedFactoryForConcreteType() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d); bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d); bind(MustangInsuranceFactory.class).toProvider( FactoryProvider.newFactory(MustangInsuranceFactory.class, MustangInsurance.class)); bind(CamaroInsuranceFactory.class).toProvider( FactoryProvider.newFactory(CamaroInsuranceFactory.class, CamaroInsurance.class)); } }); MustangInsuranceFactory mustangInsuranceFactory = injector.getInstance(MustangInsuranceFactory.class); CamaroInsuranceFactory camaroInsuranceFactory = injector.getInstance(CamaroInsuranceFactory.class); Mustang mustang = new Mustang(5000d, Color.BLACK); MustangInsurance mustangPolicy = (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d); assertEquals(800.0d, mustangPolicy.premium); assertEquals(50000.0d, mustangPolicy.limit); Camaro camaro = new Camaro(3000, 1967, Color.BLUE); CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d); assertEquals(800.0d, camaroPolicy.premium); assertEquals(100000.0d, camaroPolicy.limit); } public interface InsuranceFactory { public Insurance create(T car, double premium); } public void testAssistedFactoryForParameterizedType() { final TypeLiteral> mustangInsuranceFactoryType = new TypeLiteral>() {}; final TypeLiteral> camaroInsuranceFactoryType = new TypeLiteral>() {}; Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d); bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d); bind(mustangInsuranceFactoryType).toProvider(FactoryProvider.newFactory( mustangInsuranceFactoryType, TypeLiteral.get(MustangInsurance.class))); bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory( camaroInsuranceFactoryType, TypeLiteral.get(CamaroInsurance.class))); } }); InsuranceFactory mustangInsuranceFactory = injector.getInstance(Key.get(mustangInsuranceFactoryType)); InsuranceFactory camaroInsuranceFactory = injector.getInstance(Key.get(camaroInsuranceFactoryType)); Mustang mustang = new Mustang(5000d, Color.BLACK); MustangInsurance mustangPolicy = (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d); assertEquals(800.0d, mustangPolicy.premium); assertEquals(50000.0d, mustangPolicy.limit); Camaro camaro = new Camaro(3000, 1967, Color.BLUE); CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d); assertEquals(800.0d, camaroPolicy.premium); assertEquals(100000.0d, camaroPolicy.limit); } public static class AutoInsurance implements Insurance { private final double premium; private final double limit; private final T car; @Inject public AutoInsurance(double limit, @Assisted T car, @Assisted double premium) { this.limit = limit; this.car = car; this.premium = premium; } public void sell() {} } public void testAssistedFactoryForTypeVariableParameters() { final TypeLiteral> camaroInsuranceFactoryType = new TypeLiteral>() {}; Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(50000.0d); bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory( camaroInsuranceFactoryType, new TypeLiteral>() {})); } }); InsuranceFactory camaroInsuranceFactory = injector.getInstance(Key.get(camaroInsuranceFactoryType)); Camaro camaro = new Camaro(3000, 1967, Color.BLUE); AutoInsurance camaroPolicy = (AutoInsurance) camaroInsuranceFactory.create(camaro, 800.0d); assertEquals(800.0d, camaroPolicy.premium); assertEquals(50000.0d, camaroPolicy.limit); assertEquals(camaro, camaroPolicy.car); } public void testInjectingAndUsingInjector() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(ColoredCarFactory.class).toProvider( FactoryProvider.newFactory(ColoredCarFactory.class, Segway.class)); } }); ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); Segway green = (Segway)carFactory.create(Color.GREEN); assertSame(Color.GREEN, green.getColor()); assertSame(Color.GREEN, green.getColor()); Segway pink = (Segway)carFactory.create(Color.PINK); assertSame(Color.PINK, pink.getColor()); assertSame(Color.PINK, pink.getColor()); assertSame(Color.GREEN, green.getColor()); } static class Segway implements Car { @Inject Injector injector; Color getColor() { return injector.getInstance(Key.get(Color.class, FactoryProvider2.DEFAULT_ANNOTATION)); } } } guice-3.0/extensions/assistedinject/test/com/google/inject/assistedinject/ExtensionSpiTest.java0000644000175000017500000002142411456375360033230 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import static com.google.inject.name.Names.named; import com.google.inject.AbstractModule; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Stage; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Iterables; import com.google.inject.internal.util.Lists; import com.google.inject.name.Named; import com.google.inject.spi.DefaultBindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; import junit.framework.AssertionFailedError; import junit.framework.TestCase; import java.util.List; import java.util.Set; import java.util.logging.Logger; /** * Tests for AssistedInject Spi. * * @author ramakrishna@google.com (Ramakrishna Rajanna) */ public class ExtensionSpiTest extends TestCase { public final void testSpiOnElements() throws Exception { AssistedInjectSpiVisitor visitor = new AssistedInjectSpiVisitor(); Integer count = 0; for(Element element : Elements.getElements(new Module())) { if(element instanceof Binding) { assertEquals(count++, ((Binding)element).acceptTargetVisitor(visitor)); } } validateVisitor(visitor); } public void testSpiOnVisitor() throws Exception { AssistedInjectSpiVisitor visitor = new AssistedInjectSpiVisitor(); Integer count = 0; Injector injector = Guice.createInjector(new Module()); for(Binding binding : injector.getBindings().values()) { assertEquals(count++, binding.acceptTargetVisitor(visitor)); } validateVisitor(visitor); } private void validateVisitor(AssistedInjectSpiVisitor visitor) throws Exception { assertEquals(1, visitor.assistedBindingCount); List assistedMethods = Lists.newArrayList(Iterables.getOnlyElement( visitor.assistedInjectBindings).getAssistedMethods()); assertEquals(7, assistedMethods.size()); assertEquals(1, visitor.assistedBindingCount); assertEquals(1, visitor.assistedInjectBindings.size()); // Validate for each of the methods in AnimalFactory validateCreateAStrangeCatAsAnimal(assistedMethods.get(0)); validatecreateStrangeCatWithConstructorForOwner(assistedMethods.get(1)); validatecreateStrangeCatWithConstructorForAge(assistedMethods.get(2)); validateCreateCatWithANonAssistedDependency(assistedMethods.get(3)); validateCreateCat(assistedMethods.get(4)); validateCreateASimpleCatAsAnimal(assistedMethods.get(5)); validateCreateCatWithNonAssistedDependencies(assistedMethods.get(6)); } private void validateCreateAStrangeCatAsAnimal(AssistedMethod assistedMethod) { validateAssistedMethod(assistedMethod, "createAStrangeCatAsAnimal", StrangeCat.class, ImmutableList.>of()); } private void validatecreateStrangeCatWithConstructorForOwner(AssistedMethod assistedMethod) { validateAssistedMethod(assistedMethod, "createStrangeCatWithConstructorForOwner", StrangeCat.class, ImmutableList.>of()); } private void validatecreateStrangeCatWithConstructorForAge(AssistedMethod assistedMethod) { validateAssistedMethod(assistedMethod, "createStrangeCatWithConstructorForAge", StrangeCat.class, ImmutableList.>of()); } private void validateCreateCatWithANonAssistedDependency(AssistedMethod assistedMethod) throws Exception { validateAssistedMethod(assistedMethod, "createCatWithANonAssistedDependency", CatWithAName.class, ImmutableList.>of(Key.get(String.class, named("catName2")))); } private void validateCreateCat(AssistedMethod assistedMethod) throws Exception { validateAssistedMethod(assistedMethod, "createCat", Cat.class, ImmutableList.>of()); } private void validateCreateASimpleCatAsAnimal(AssistedMethod assistedMethod) { validateAssistedMethod(assistedMethod, "createASimpleCatAsAnimal", SimpleCat.class, ImmutableList.>of()); } private void validateCreateCatWithNonAssistedDependencies(AssistedMethod assistedMethod) { List> dependencyKeys = ImmutableList.>of( Key.get(String.class, named("catName1")), Key.get(String.class, named("petName")), Key.get(Integer.class, named("age"))); validateAssistedMethod(assistedMethod, "createCatWithNonAssistedDependencies", ExplodingCat.class, dependencyKeys); } private void validateAssistedMethod(AssistedMethod assistedMethod, String factoryMethodName, Class clazz, List> dependencyKeys){ assertEquals(factoryMethodName, assistedMethod.getFactoryMethod().getName()); assertEquals(clazz, assistedMethod.getImplementationConstructor().getDeclaringClass()); assertEquals(dependencyKeys.size(), assistedMethod.getDependencies().size()); for (Dependency dependency : assistedMethod.getDependencies()) { assertTrue(dependencyKeys.contains(dependency.getKey())); } assertEquals(clazz, assistedMethod.getImplementationType().getType()); } interface AnimalFactory { Cat createCat(String owner); CatWithAName createCatWithANonAssistedDependency(String owner); @Named("SimpleCat") Animal createASimpleCatAsAnimal(String owner); Animal createAStrangeCatAsAnimal(String owner); StrangeCat createStrangeCatWithConstructorForOwner(String owner); StrangeCat createStrangeCatWithConstructorForAge(Integer age); ExplodingCat createCatWithNonAssistedDependencies(String owner); } interface Animal {} private static class Cat implements Animal { @Inject Cat(@Assisted String owner) {} } private static class SimpleCat implements Animal { @Inject SimpleCat(@Assisted String owner) { } } private static class StrangeCat implements Animal { @AssistedInject StrangeCat(@Assisted String owner) {} @AssistedInject StrangeCat(@Assisted Integer age) {} } private static class ExplodingCat implements Animal { @Inject public ExplodingCat(@Named("catName1") String name, @Assisted String owner, @Named("age") Integer age, @Named("petName") String petName) {} } private static class CatWithAName extends Cat { @Inject CatWithAName(@Assisted String owner, @Named("catName2") String name) { super(owner); } } public class Module extends AbstractModule{ @Override protected void configure() { bind(String.class).annotatedWith(named("catName1")).toInstance("kitty1"); bind(String.class).annotatedWith(named("catName2")).toInstance("kitty2"); bind(String.class).annotatedWith(named("petName")).toInstance("pussy"); bind(Integer.class).annotatedWith(named("age")).toInstance(12); install(new FactoryModuleBuilder() .implement(Animal.class, StrangeCat.class) .implement(Animal.class, named("SimpleCat"), SimpleCat.class) .build(AnimalFactory.class)); } } public class AssistedInjectSpiVisitor extends DefaultBindingTargetVisitor implements AssistedInjectTargetVisitor { private final Set allowedClasses = ImmutableSet. of( Injector.class, Stage.class, Logger.class, String.class, Integer.class); private int assistedBindingCount = 0; private int currentCount = 0; private List> assistedInjectBindings = Lists.newArrayList(); public Integer visit(AssistedInjectBinding assistedInjectBinding) { assistedInjectBindings.add(assistedInjectBinding); assistedBindingCount++; return currentCount++; } @Override protected Integer visitOther(Binding binding) { if(!allowedClasses.contains(binding.getKey().getTypeLiteral().getRawType())) { throw new AssertionFailedError("invalid other binding: " + binding); } return currentCount++; } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootguice-3.0/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryModuleBuilderTest.javaguice-3.0/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryModuleBuilderTest.j0000644000175000017500000004175611521022772034173 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import static com.google.inject.Asserts.assertContains; import static com.google.inject.name.Names.named; import java.awt.Color; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import junit.framework.TestCase; import com.google.inject.AbstractModule; import com.google.inject.Binding; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provides; import com.google.inject.Singleton; import com.google.inject.Stage; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Iterables; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.spi.Dependency; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.Message; public class FactoryModuleBuilderTest extends TestCase { public void testImplicitForwardingAssistedBindingFailsWithInterface() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Car.class).to(Golf.class); install(new FactoryModuleBuilder().build(ColoredCarFactory.class)); } }); fail(); } catch (CreationException ce) { assertContains( ce.getMessage(), "1) " + Car.class.getName() + " is an interface, not a concrete class.", "Unable to create AssistedInject factory.", "while locating " + Car.class.getName(), "at " + ColoredCarFactory.class.getName() + ".create("); assertEquals(1, ce.getErrorMessages().size()); } } public void testImplicitForwardingAssistedBindingFailsWithAbstractClass() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(AbstractCar.class).to(ArtCar.class); install(new FactoryModuleBuilder().build(ColoredAbstractCarFactory.class)); } }); fail(); } catch (CreationException ce) { assertContains( ce.getMessage(), "1) " + AbstractCar.class.getName() + " is abstract, not a concrete class.", "Unable to create AssistedInject factory.", "while locating " + AbstractCar.class.getName(), "at " + ColoredAbstractCarFactory.class.getName() + ".create("); assertEquals(1, ce.getErrorMessages().size()); } } public void testImplicitForwardingAssistedBindingCreatesNewObjects() { final Mustang providedMustang = new Mustang(Color.BLUE); Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(MustangFactory.class)); } @Provides Mustang provide() { return providedMustang; } }); assertSame(providedMustang, injector.getInstance(Mustang.class)); MustangFactory factory = injector.getInstance(MustangFactory.class); Mustang created = factory.create(Color.GREEN); assertNotSame(providedMustang, created); assertEquals(Color.BLUE, providedMustang.color); assertEquals(Color.GREEN, created.color); } public void testExplicitForwardingAssistedBindingFailsWithInterface() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Volkswagen.class).to(Golf.class); install(new FactoryModuleBuilder() .implement(Car.class, Volkswagen.class) .build(ColoredCarFactory.class)); } }); fail(); } catch (CreationException ce) { assertContains( ce.getMessage(), "1) " + Volkswagen.class.getName() + " is an interface, not a concrete class.", "Unable to create AssistedInject factory.", "while locating " + Volkswagen.class.getName(), "while locating " + Car.class.getName(), "at " + ColoredCarFactory.class.getName() + ".create("); assertEquals(1, ce.getErrorMessages().size()); } } public void testExplicitForwardingAssistedBindingFailsWithAbstractClass() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(AbstractCar.class).to(ArtCar.class); install(new FactoryModuleBuilder() .implement(Car.class, AbstractCar.class) .build(ColoredCarFactory.class)); } }); fail(); } catch (CreationException ce) { assertContains( ce.getMessage(), "1) " + AbstractCar.class.getName() + " is abstract, not a concrete class.", "Unable to create AssistedInject factory.", "while locating " + AbstractCar.class.getName(), "while locating " + Car.class.getName(), "at " + ColoredCarFactory.class.getName() + ".create("); assertEquals(1, ce.getErrorMessages().size()); } } public void testExplicitForwardingAssistedBindingCreatesNewObjects() { final Mustang providedMustang = new Mustang(Color.BLUE); Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().implement(Car.class, Mustang.class).build( ColoredCarFactory.class)); } @Provides Mustang provide() { return providedMustang; } }); assertSame(providedMustang, injector.getInstance(Mustang.class)); ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class); Mustang created = (Mustang)factory.create(Color.GREEN); assertNotSame(providedMustang, created); assertEquals(Color.BLUE, providedMustang.color); assertEquals(Color.GREEN, created.color); } public void testAnnotatedAndParentBoundReturnValue() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Car.class).to(Golf.class); bind(Integer.class).toInstance(911); bind(Double.class).toInstance(5.0d); install(new FactoryModuleBuilder() .implement(Car.class, Names.named("german"), Beetle.class) .implement(Car.class, Names.named("american"), Mustang.class) .build(AnnotatedVersatileCarFactory.class)); } }); AnnotatedVersatileCarFactory factory = injector.getInstance(AnnotatedVersatileCarFactory.class); assertTrue(factory.getGermanCar(Color.BLACK) instanceof Beetle); assertTrue(injector.getInstance(Car.class) instanceof Golf); } public void testParentBoundReturnValue() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Car.class).to(Golf.class); bind(Double.class).toInstance(5.0d); install(new FactoryModuleBuilder() .implement(Car.class, Mustang.class) .build(ColoredCarFactory.class)); } }); ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class); assertTrue(factory.create(Color.RED) instanceof Mustang); assertTrue(injector.getInstance(Car.class) instanceof Golf); } public void testConfigureAnnotatedReturnValue() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder() .implement(Car.class, Names.named("german"), Beetle.class) .implement(Car.class, Names.named("american"), Mustang.class) .build(AnnotatedVersatileCarFactory.class)); } }); AnnotatedVersatileCarFactory factory = injector.getInstance(AnnotatedVersatileCarFactory.class); assertTrue(factory.getGermanCar(Color.GRAY) instanceof Beetle); assertTrue(factory.getAmericanCar(Color.BLACK) instanceof Mustang); } public void testNoBindingAssistedInject() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(MustangFactory.class)); } }); MustangFactory factory = injector.getInstance(MustangFactory.class); Mustang mustang = factory.create(Color.BLUE); assertEquals(Color.BLUE, mustang.color); } public void testBindingAssistedInject() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder() .implement(Car.class, Mustang.class) .build(ColoredCarFactory.class)); } }); ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class); Mustang mustang = (Mustang) factory.create(Color.BLUE); assertEquals(Color.BLUE, mustang.color); } public void testMultipleReturnTypes() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Double.class).toInstance(5.0d); install(new FactoryModuleBuilder().build(VersatileCarFactory.class)); } }); VersatileCarFactory factory = injector.getInstance(VersatileCarFactory.class); Mustang mustang = factory.getMustang(Color.RED); assertEquals(Color.RED, mustang.color); Beetle beetle = factory.getBeetle(Color.GREEN); assertEquals(Color.GREEN, beetle.color); } public void testParameterizedClassesWithNoImplements() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(new TypeLiteral>() {})); } }); Foo.Factory factory = injector.getInstance(Key.get(new TypeLiteral>() {})); @SuppressWarnings("unused") Foo foo = factory.create(new Bar()); } public void testGenericErrorMessageMakesSense() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(Key.get(Foo.Factory.class))); } }); fail(); } catch(CreationException ce ) { // Assert not only that it's the correct message, but also that it's the *only* message. Collection messages = ce.getErrorMessages(); assertEquals( Foo.Factory.class.getName() + " cannot be used as a key; It is not fully specified.", Iterables.getOnlyElement(messages).getMessage()); } } interface Car {} interface Volkswagen extends Car {} interface ColoredCarFactory { Car create(Color color); } interface MustangFactory { Mustang create(Color color); } interface VersatileCarFactory { Mustang getMustang(Color color); Beetle getBeetle(Color color); } interface AnnotatedVersatileCarFactory { @Named("german") Car getGermanCar(Color color); @Named("american") Car getAmericanCar(Color color); } public static class Golf implements Volkswagen {} public static class Mustang implements Car { private final Color color; @Inject public Mustang(@Assisted Color color) { this.color = color; } } public static class Beetle implements Car { private final Color color; @Inject public Beetle(@Assisted Color color) { this.color = color; } } public static class Foo { static interface Factory { Foo create(Bar bar); } @Inject Foo(@Assisted Bar bar, Baz baz) {} } public static class Bar {} public static class Baz {} abstract static class AbstractCar implements Car {} interface ColoredAbstractCarFactory { AbstractCar create(Color color); } public static class ArtCar extends AbstractCar {} public void testFactoryBindingDependencies() { // validate dependencies work in all stages & as a raw element, // and that dependencies work for methods, fields, constructors, // and for @AssistedInject constructors too. Module module = new AbstractModule() { @Override protected void configure() { bind(Integer.class).toInstance(42); bind(Double.class).toInstance(4.2d); bind(Float.class).toInstance(4.2f); bind(String.class).annotatedWith(named("dog")).toInstance("dog"); bind(String.class).annotatedWith(named("cat1")).toInstance("cat1"); bind(String.class).annotatedWith(named("cat2")).toInstance("cat2"); bind(String.class).annotatedWith(named("cat3")).toInstance("cat3"); bind(String.class).annotatedWith(named("arbitrary")).toInstance("fail!"); install(new FactoryModuleBuilder() .implement(Animal.class, Dog.class) .build(AnimalHouse.class)); } }; Set> expectedKeys = ImmutableSet.>of( Key.get(Integer.class), Key.get(Double.class), Key.get(Float.class), Key.get(String.class, named("dog")), Key.get(String.class, named("cat1")), Key.get(String.class, named("cat2")), Key.get(String.class, named("cat3")) ); Injector injector = Guice.createInjector(module); validateDependencies(expectedKeys, injector.getBinding(AnimalHouse.class)); injector = Guice.createInjector(Stage.TOOL, module); validateDependencies(expectedKeys, injector.getBinding(AnimalHouse.class)); List elements = Elements.getElements(module); boolean found = false; for(Element element : elements) { if(element instanceof Binding) { Binding binding = (Binding)element; if(binding.getKey().equals(Key.get(AnimalHouse.class))) { found = true; validateDependencies(expectedKeys, binding); break; } } } assertTrue(found); } private void validateDependencies(Set> expectedKeys, Binding binding) { Set> dependencies = ((HasDependencies)binding).getDependencies(); Set> actualKeys = new HashSet>(); for(Dependency dependency : dependencies) { actualKeys.add(dependency.getKey()); } assertEquals(expectedKeys, actualKeys); } interface AnimalHouse { Animal createAnimal(String name); Cat createCat(String name); Cat createCat(int age); } interface Animal {} private static class Dog implements Animal { @Inject int a; @Inject Dog(@Assisted String a, double b) {} @Inject void register(@Named("dog") String a) {} } private static class Cat implements Animal { @Inject float a; @AssistedInject Cat(@Assisted String a, @Named("cat1") String b) {} @AssistedInject Cat(@Assisted int a, @Named("cat2") String b) {} @AssistedInject Cat(@Assisted byte a, @Named("catfail") String b) {} // not a dependency! @Inject void register(@Named("cat3") String a) {} } public void testFactoryPublicAndReturnTypeNotPublic() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder() .implement(Hidden.class, HiddenImpl.class) .build(NotHidden.class)); } }); } catch(CreationException ce) { assertEquals(NotHidden.class.getName() + " is public, but has a method that returns a non-public type: " + Hidden.class.getName() + ". Due to limitations with java.lang.reflect.Proxy, this is not allowed. " + "Please either make the factory non-public or the return type public.", Iterables.getOnlyElement(ce.getErrorMessages()).getMessage()); } } interface Hidden {} public static class HiddenImpl implements Hidden {} public interface NotHidden { Hidden create(); } public void testSingletonScopeOnAssistedClassIsIgnored() { // production stage is important, because it will trigger eager singleton creation Injector injector = Guice.createInjector(Stage.PRODUCTION, new AbstractModule() { @Override protected void configure() { install(new FactoryModuleBuilder().build(SingletonFactory.class)); } }); SingletonFactory factory = injector.getInstance(SingletonFactory.class); assertNotSame(factory.create("foo"), factory.create("bar")); } interface SingletonFactory { AssistedSingleton create(String string); } @Singleton static class AssistedSingleton { @Inject public AssistedSingleton(@Assisted String string) { } } } guice-3.0/extensions/assistedinject/src/0000755000175000017500000000000011527757646020372 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/src/com/0000755000175000017500000000000011214265012021116 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/src/com/google/0000755000175000017500000000000011214265012022372 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/src/com/google/inject/0000755000175000017500000000000011214265012023646 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/0000755000175000017500000000000011456373542026702 5ustar drazzibdrazzibguice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/package-info.java0000644000175000017500000000140411461123326032055 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Extension for combining factory interfaces with injection; this extension requires {@code * guice-assistedinject-3.0.jar}. */ package com.google.inject.assistedinject;././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootguice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectTargetVisitor.javaguice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectTargetVisitor0000644000175000017500000000241511463270166034266 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.spi.BindingTargetVisitor; /** * A visitor for the AssistedInject extension. *

* If your {@link BindingTargetVisitor} implements this interface, bindings created by using * {@link FactoryModuleBuilder} will be visited through this interface. * * @since 3.0 * @author ramakrishna@google.com (Ramakrishna Rajanna) */ public interface AssistedInjectTargetVisitor extends BindingTargetVisitor { /** * Visits an {@link AssistedInjectBinding} created through {@link FactoryModuleBuilder}. */ V visit(AssistedInjectBinding assistedInjectBinding); } guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/BindingCollector.java0000644000175000017500000000312111413604604032750 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.ConfigurationException; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Maps; import com.google.inject.spi.Message; import java.util.Collections; import java.util.Map; /** * Utility class for collecting factory bindings. Used for configuring {@link FactoryProvider2}. * * @author schmitt@google.com (Peter Schmitt) */ class BindingCollector { private final Map, TypeLiteral> bindings = Maps.newHashMap(); public BindingCollector addBinding(Key key, TypeLiteral target) { if (bindings.containsKey(key)) { throw new ConfigurationException(ImmutableSet.of( new Message("Only one implementation can be specified for " + key))); } bindings.put(key, target); return this; } public Map, TypeLiteral> getBindings() { return Collections.unmodifiableMap(bindings); } } guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectBinding.java0000644000175000017500000000225211463267446033760 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.Key; import java.util.Collection; /** * A binding for a factory created by FactoryModuleBuilder. * * @param The fully qualified type of the factory. * * @since 3.0 * @author ramakrishna@google.com (Ramakrishna Rajanna) */ public interface AssistedInjectBinding { /** Returns the {@link Key} for the factory binding. */ Key getKey(); /** Returns an {@link AssistedMethod} for each method in the factory. */ Collection getAssistedMethods(); } guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedConstructor.java0000644000175000017500000000620111424342652033562 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.Inject; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Lists; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Internal respresentation of a constructor annotated with * {@link AssistedInject} * * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) */ class AssistedConstructor { private final Constructor constructor; private final ParameterListKey assistedParameters; private final List allParameters; @SuppressWarnings("unchecked") public AssistedConstructor(Constructor constructor, List> parameterTypes) { this.constructor = constructor; Annotation[][] annotations = constructor.getParameterAnnotations(); List typeList = Lists.newArrayList(); allParameters = new ArrayList(); // categorize params as @Assisted or @Injected for (int i = 0; i < parameterTypes.size(); i++) { Parameter parameter = new Parameter(parameterTypes.get(i).getType(), annotations[i]); allParameters.add(parameter); if (parameter.isProvidedByFactory()) { typeList.add(parameter.getType()); } } this.assistedParameters = new ParameterListKey(typeList); } /** * Returns the {@link ParameterListKey} for this constructor. The * {@link ParameterListKey} is created from the ordered list of {@link Assisted} * constructor parameters. */ public ParameterListKey getAssistedParameters() { return assistedParameters; } /** * Returns an ordered list of all constructor parameters (both * {@link Assisted} and {@link Inject}ed). */ public List getAllParameters() { return allParameters; } public Set> getDeclaredExceptions() { return new HashSet>(Arrays.asList(constructor.getExceptionTypes())); } /** * Returns an instance of T, constructed using this constructor, with the * supplied arguments. */ public T newInstance(Object[] args) throws Throwable { constructor.setAccessible(true); try { return constructor.newInstance(args); } catch (InvocationTargetException e) { throw e.getCause(); } } @Override public String toString() { return constructor.toString(); } } guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java0000644000175000017500000003011411523505454033622 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.AbstractModule; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import java.lang.annotation.Annotation; /** * Provides a factory that combines the caller's arguments with injector-supplied values to * construct objects. * *

Defining a factory

* Create an interface whose methods return the constructed type, or any of its supertypes. The * method's parameters are the arguments required to build the constructed type. * *
public interface PaymentFactory {
 *   Payment create(Date startDate, Money amount);
 * }
* * You can name your factory methods whatever you like, such as create, createPayment * or newPayment. * *

Creating a type that accepts factory parameters

* {@code constructedType} is a concrete class with an {@literal @}{@link com.google.inject.Inject * Inject}-annotated constructor. In addition to injector-supplied parameters, the constructor * should have parameters that match each of the factory method's parameters. Each factory-supplied * parameter requires an {@literal @}{@link Assisted} annotation. This serves to document that the * parameter is not bound by your application's modules. * *
public class RealPayment implements Payment {
 *   {@literal @}Inject
 *   public RealPayment(
 *      CreditService creditService,
 *      AuthService authService,
 *      {@literal @}Assisted Date startDate,
 *      {@literal @}Assisted Money amount) {
 *     ...
 *   }
 * }
* *

Multiple factory methods for the same type

* If the factory contains many methods that return the same type, you can create multiple * constructors in your concrete class, each constructor marked with with * {@literal @}{@link AssistedInject}, in order to match the different parameters types of the * factory methods. * *
public interface PaymentFactory {
 *    Payment create(Date startDate, Money amount);
 *    Payment createWithoutDate(Money amount);
 * }
 * 
 * public class RealPayment implements Payment {
 *  {@literal @}AssistedInject
 *   public RealPayment(
 *      CreditService creditService,
 *      AuthService authService,
 *     {@literal @}Assisted Date startDate,
 *     {@literal @}Assisted Money amount) {
 *     ...
 *   }
 *   
 *  {@literal @}AssistedInject
 *   public RealPayment(
 *      CreditService creditService,
 *      AuthService authService,
 *     {@literal @}Assisted Money amount) {
 *     ...
 *   }   
 * }
* *

Configuring simple factories

* In your {@link Module module}, install a {@code FactoryModuleBuilder} that creates the * factory: * *
install(new FactoryModuleBuilder()
 *     .implement(Payment.class, RealPayment.class)
 *     .build(PaymentFactory.class);
* * As a side-effect of this binding, Guice will inject the factory to initialize it for use. The * factory cannot be used until the injector has been initialized. * *

Configuring complex factories

* Factories can create an arbitrary number of objects, one per each method. Each factory * method can be configured using .implement. * *
public interface OrderFactory {
 *    Payment create(Date startDate, Money amount);
 *    Shipment create(Customer customer, Item item);
 *    Receipt create(Payment payment, Shipment shipment);
 * }
 * 
 * [...]
 * 
 * install(new FactoryModuleBuilder()
 *     .implement(Payment.class, RealPayment.class)
 *     // excluding .implement for Shipment means the implementation class
 *     // will be 'Shipment' itself, which is legal if it's not an interface.
 *     .implement(Receipt.class, RealReceipt.class)
 *     .build(OrderFactory.class);
* * *

Using the factory

* Inject your factory into your application classes. When you use the factory, your arguments * will be combined with values from the injector to construct an instance. * *
public class PaymentAction {
 *   {@literal @}Inject private PaymentFactory paymentFactory;
 *
 *   public void doPayment(Money amount) {
 *     Payment payment = paymentFactory.create(new Date(), amount);
 *     payment.apply();
 *   }
 * }
* *

Making parameter types distinct

* The types of the factory method's parameters must be distinct. To use multiple parameters of * the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate the * parameters. The names must be applied to the factory method's parameters: * *
public interface PaymentFactory {
 *   Payment create(
 *       {@literal @}Assisted("startDate") Date startDate,
 *       {@literal @}Assisted("dueDate") Date dueDate,
 *       Money amount);
 * } 
* * ...and to the concrete type's constructor parameters: * *
public class RealPayment implements Payment {
 *   {@literal @}Inject
 *   public RealPayment(
 *      CreditService creditService,
 *      AuthService authService,
 *      {@literal @}Assisted("startDate") Date startDate,
 *      {@literal @}Assisted("dueDate") Date dueDate,
 *      {@literal @}Assisted Money amount) {
 *     ...
 *   }
 * }
* *

Values are created by Guice

* Returned factories use child injectors to create values. The values are eligible for method * interception. In addition, {@literal @}{@literal Inject} members will be injected before they are * returned. * *

More configuration options

* In addition to simply specifying an implementation class for any returned type, factories' return * values can be automatic or can be configured to use annotations: *

* If you just want to return the types specified in the factory, do not configure any * implementations: * *

public interface FruitFactory {
 *   Apple getApple(Color color);
 * }
 * ...
 * protected void configure() {
 *   install(new FactoryModuleBuilder().build(FruitFactory.class));
 * }
* * Note that any type returned by the factory in this manner needs to be an implementation class. *

* To return two different implementations for the same interface from your factory, use binding * annotations on your return types: * *

interface CarFactory {
 *   {@literal @}Named("fast") Car getFastCar(Color color);
 *   {@literal @}Named("clean") Car getCleanCar(Color color);
 * }
 * ...
 * protected void configure() {
 *   install(new FactoryModuleBuilder()
 *       .implement(Car.class, Names.named("fast"), Porsche.class)
 *       .implement(Car.class, Names.named("clean"), Prius.class)
 *       .build(CarFactory.class));
 * }
* *

Implementation limitations

* As a limitation of the implementation, it is prohibited to declare a factory method that * accepts a {@code Provider} as one of its arguments. * * @since 3.0 * @author schmitt@google.com (Peter Schmitt) */ public final class FactoryModuleBuilder { private final BindingCollector bindings = new BindingCollector(); /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(Class source, Class target) { return implement(source, TypeLiteral.get(target)); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(Class source, TypeLiteral target) { return implement(TypeLiteral.get(source), target); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(TypeLiteral source, Class target) { return implement(source, TypeLiteral.get(target)); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(TypeLiteral source, TypeLiteral target) { return implement(Key.get(source), target); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(Class source, Annotation annotation, Class target) { return implement(source, annotation, TypeLiteral.get(target)); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(Class source, Annotation annotation, TypeLiteral target) { return implement(TypeLiteral.get(source), annotation, target); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(TypeLiteral source, Annotation annotation, Class target) { return implement(source, annotation, TypeLiteral.get(target)); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(TypeLiteral source, Annotation annotation, TypeLiteral target) { return implement(Key.get(source, annotation), target); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(Class source, Class annotationType, Class target) { return implement(source, annotationType, TypeLiteral.get(target)); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(Class source, Class annotationType, TypeLiteral target) { return implement(TypeLiteral.get(source), annotationType, target); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(TypeLiteral source, Class annotationType, Class target) { return implement(source, annotationType, TypeLiteral.get(target)); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(TypeLiteral source, Class annotationType, TypeLiteral target) { return implement(Key.get(source, annotationType), target); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(Key source, Class target) { return implement(source, TypeLiteral.get(target)); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public FactoryModuleBuilder implement(Key source, TypeLiteral target) { bindings.addBinding(source, target); return this; } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public Module build(Class factoryInterface) { return build(TypeLiteral.get(factoryInterface)); } /** * See the factory configuration examples at {@link FactoryModuleBuilder}. */ public Module build(TypeLiteral factoryInterface) { return build(Key.get(factoryInterface)); } public Module build(final Key factoryInterface) { return new AbstractModule() { @Override protected void configure() { Provider provider = new FactoryProvider2(factoryInterface, bindings); bind(factoryInterface).toProvider(provider); } }; } } guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/Assisted.java0000644000175000017500000000300511214265012031302 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.BindingAnnotation; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Annotates an injected parameter or field whose value comes from an argument to a factory method. * * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) */ @BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME) public @interface Assisted { /** * The unique name for this parameter. This is matched to the {@literal @Assisted} constructor * parameter with the same value. Names are not necessary when the parameter types are distinct. */ String value() default ""; }guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/ParameterListKey.java0000644000175000017500000000326011214265012032753 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.TypeLiteral; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * A list of {@link TypeLiteral}s to match an injectable Constructor's assited * parameter types to the corresponding factory method. * * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) */ class ParameterListKey { private final List paramList; public ParameterListKey(List paramList) { this.paramList = new ArrayList(paramList); } public ParameterListKey(Type[] types) { this(Arrays.asList(types)); } @Override public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof ParameterListKey)) { return false; } ParameterListKey other = (ParameterListKey) o; return paramList.equals(other.paramList); } @Override public int hashCode() { return paramList.hashCode(); } @Override public String toString() { return paramList.toString(); } }guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/Parameter.java0000644000175000017500000001160611413604604031456 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.ConfigurationException; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.internal.Annotations; import static com.google.inject.internal.util.Preconditions.checkArgument; import java.lang.annotation.Annotation; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; /** * Models a method or constructor parameter. * * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) */ class Parameter { private final Type type; private final boolean isAssisted; private final Annotation bindingAnnotation; private final boolean isProvider; private volatile Provider provider; public Parameter(Type type, Annotation[] annotations) { this.type = type; this.bindingAnnotation = getBindingAnnotation(annotations); this.isAssisted = hasAssistedAnnotation(annotations); this.isProvider = isProvider(type); } public boolean isProvidedByFactory() { return isAssisted; } public Type getType() { return type; } @Override public String toString() { StringBuilder result = new StringBuilder(); if (isAssisted) { result.append("@Assisted"); result.append(" "); } if (bindingAnnotation != null) { result.append(bindingAnnotation.toString()); result.append(" "); } result.append(type.toString()); return result.toString(); } private boolean hasAssistedAnnotation(Annotation[] annotations) { for (Annotation annotation : annotations) { if (annotation.annotationType().equals(Assisted.class)) { return true; } } return false; } /** * Returns the Guice {@link Key} for this parameter. */ public Object getValue(Injector injector) { if (null == provider) { synchronized (this) { if (null == provider) { provider = isProvider ? injector.getProvider(getBindingForType(getProvidedType(type))) : injector.getProvider(getPrimaryBindingKey()); } } } return isProvider ? provider : provider.get(); } public boolean isBound(Injector injector) { return isBound(injector, getPrimaryBindingKey()) || isBound(injector, fixAnnotations(getPrimaryBindingKey())); } private boolean isBound(Injector injector, Key key) { // This method is particularly lame - we really need an API that can test // for any binding, implicit or explicit try { return injector.getBinding(key) != null; } catch (ConfigurationException e) { return false; } } /** * Replace annotation instances with annotation types, this is only * appropriate for testing if a key is bound and not for injecting. * * See Guice bug 125, * http://code.google.com/p/google-guice/issues/detail?id=125 */ public Key fixAnnotations(Key key) { return key.getAnnotation() == null ? key : Key.get(key.getTypeLiteral(), key.getAnnotation().annotationType()); } Key getPrimaryBindingKey() { return isProvider ? getBindingForType(getProvidedType(type)) : getBindingForType(type); } private Type getProvidedType(Type type) { return ((ParameterizedType) type).getActualTypeArguments()[0]; } private boolean isProvider(Type type) { return type instanceof ParameterizedType && ((ParameterizedType) type).getRawType() == Provider.class; } private Key getBindingForType(Type type) { return bindingAnnotation != null ? Key.get(type, bindingAnnotation) : Key.get(type); } /** * Returns the unique binding annotation from the specified list, or * {@code null} if there are none. * * @throws IllegalStateException if multiple binding annotations exist. */ private Annotation getBindingAnnotation(Annotation[] annotations) { Annotation bindingAnnotation = null; for (Annotation annotation : annotations) { if (Annotations.isBindingAnnotation(annotation.annotationType())) { checkArgument(bindingAnnotation == null, "Parameter has multiple binding annotations: %s and %s", bindingAnnotation, annotation); bindingAnnotation = annotation; } } return bindingAnnotation; } } guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java0000644000175000017500000003714411456374266032704 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.ConfigurationException; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import static com.google.inject.internal.Annotations.getKey; import com.google.inject.internal.BytecodeGen; import com.google.inject.internal.Errors; import com.google.inject.internal.ErrorsException; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Maps; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.Message; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import java.util.Set; /** * Obsolete. Prefer {@link FactoryModuleBuilder} for its more concise API and * additional capability. * *

Provides a factory that combines the caller's arguments with injector-supplied values to * construct objects. * *

Defining a factory

* Create an interface whose methods return the constructed type, or any of its supertypes. The * method's parameters are the arguments required to build the constructed type. *
public interface PaymentFactory {
 *   Payment create(Date startDate, Money amount);
 * }
* You can name your factory methods whatever you like, such as create, createPayment * or newPayment. * *

Creating a type that accepts factory parameters

* {@code constructedType} is a concrete class with an {@literal @}{@link Inject}-annotated * constructor. In addition to injector-supplied parameters, the constructor should have * parameters that match each of the factory method's parameters. Each factory-supplied parameter * requires an {@literal @}{@link Assisted} annotation. This serves to document that the parameter * is not bound by your application's modules. *
public class RealPayment implements Payment {
 *   {@literal @}Inject
 *   public RealPayment(
 *      CreditService creditService,
 *      AuthService authService,
 *      {@literal @}Assisted Date startDate,
 *      {@literal @}Assisted Money amount) {
 *     ...
 *   }
 * }
* Any parameter that permits a null value should also be annotated {@code @Nullable}. * *

Configuring factories

* In your {@link com.google.inject.Module module}, bind the factory interface to the returned * factory: *
bind(PaymentFactory.class).toProvider(
 *     FactoryProvider.newFactory(PaymentFactory.class, RealPayment.class));
* As a side-effect of this binding, Guice will inject the factory to initialize it for use. The * factory cannot be used until the injector has been initialized. * *

Using the factory

* Inject your factory into your application classes. When you use the factory, your arguments * will be combined with values from the injector to construct an instance. *
public class PaymentAction {
 *   {@literal @}Inject private PaymentFactory paymentFactory;
 *
 *   public void doPayment(Money amount) {
 *     Payment payment = paymentFactory.create(new Date(), amount);
 *     payment.apply();
 *   }
 * }
* *

Making parameter types distinct

* The types of the factory method's parameters must be distinct. To use multiple parameters of * the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate the * parameters. The names must be applied to the factory method's parameters: * *
public interface PaymentFactory {
 *   Payment create(
 *       {@literal @}Assisted("startDate") Date startDate,
 *       {@literal @}Assisted("dueDate") Date dueDate,
 *       Money amount);
 * } 
* ...and to the concrete type's constructor parameters: *
public class RealPayment implements Payment {
 *   {@literal @}Inject
 *   public RealPayment(
 *      CreditService creditService,
 *      AuthService authService,
 *      {@literal @}Assisted("startDate") Date startDate,
 *      {@literal @}Assisted("dueDate") Date dueDate,
 *      {@literal @}Assisted Money amount) {
 *     ...
 *   }
 * }
* *

Values are created by Guice

* Returned factories use child injectors to create values. The values are eligible for method * interception. In addition, {@literal @}{@literal Inject} members will be injected before they are * returned. * *

Backwards compatibility using {@literal @}AssistedInject

* Instead of the {@literal @}Inject annotation, you may annotate the constructed classes with * {@literal @}{@link AssistedInject}. This triggers a limited backwards-compatability mode. * *

Instead of matching factory method arguments to constructor parameters using their names, the * parameters are matched by their order. The first factory method argument is * used for the first {@literal @}Assisted constructor parameter, etc.. Annotation names have no * effect. * *

Returned values are not created by Guice. These types are not eligible for * method interception. They do receive post-construction member injection. * * @param The factory interface * * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) * @author dtm@google.com (Daniel Martin) * * @deprecated use {@link FactoryModuleBuilder} instead. */ @Deprecated public class FactoryProvider implements Provider, HasDependencies { /* * This class implements the old @AssistedInject implementation that manually matches constructors * to factory methods. The new child injector implementation lives in FactoryProvider2. */ private Injector injector; private final TypeLiteral factoryType; private final Map> factoryMethodToConstructor; public static Provider newFactory(Class factoryType, Class implementationType){ return newFactory(TypeLiteral.get(factoryType), TypeLiteral.get(implementationType)); } public static Provider newFactory( TypeLiteral factoryType, TypeLiteral implementationType) { Map> factoryMethodToConstructor = createMethodMapping(factoryType, implementationType); if (!factoryMethodToConstructor.isEmpty()) { return new FactoryProvider(factoryType, factoryMethodToConstructor); } else { BindingCollector collector = new BindingCollector(); // Preserving backwards-compatibility: Map all return types in a factory // interface to the passed implementation type. Errors errors = new Errors(); Key implementationKey = Key.get(implementationType); if (implementationType != null) { try { for (Method method : factoryType.getRawType().getMethods()) { Key returnType = getKey(factoryType.getReturnType(method), method, method.getAnnotations(), errors); if (!implementationKey.equals(returnType)) { collector.addBinding(returnType, implementationType); } } } catch (ErrorsException e) { throw new ConfigurationException(e.getErrors().getMessages()); } } return new FactoryProvider2(Key.get(factoryType), collector); } } private FactoryProvider(TypeLiteral factoryType, Map> factoryMethodToConstructor) { this.factoryType = factoryType; this.factoryMethodToConstructor = factoryMethodToConstructor; checkDeclaredExceptionsMatch(); } @Inject void setInjectorAndCheckUnboundParametersAreInjectable(Injector injector) { this.injector = injector; for (AssistedConstructor c : factoryMethodToConstructor.values()) { for (Parameter p : c.getAllParameters()) { if(!p.isProvidedByFactory() && !paramCanBeInjected(p, injector)) { // this is lame - we're not using the proper mechanism to add an // error to the injector. Throughout this class we throw exceptions // to add errors, which isn't really the best way in Guice throw newConfigurationException("Parameter of type '%s' is not injectable or annotated " + "with @Assisted for Constructor '%s'", p, c); } } } } private void checkDeclaredExceptionsMatch() { for (Map.Entry> entry : factoryMethodToConstructor.entrySet()) { for (Class constructorException : entry.getValue().getDeclaredExceptions()) { if (!isConstructorExceptionCompatibleWithFactoryExeception( constructorException, entry.getKey().getExceptionTypes())) { throw newConfigurationException("Constructor %s declares an exception, but no compatible " + "exception is thrown by the factory method %s", entry.getValue(), entry.getKey()); } } } } private boolean isConstructorExceptionCompatibleWithFactoryExeception( Class constructorException, Class[] factoryExceptions) { for (Class factoryException : factoryExceptions) { if (factoryException.isAssignableFrom(constructorException)) { return true; } } return false; } private boolean paramCanBeInjected(Parameter parameter, Injector injector) { return parameter.isBound(injector); } private static Map> createMethodMapping( TypeLiteral factoryType, TypeLiteral implementationType) { List> constructors = Lists.newArrayList(); for (Constructor constructor : implementationType.getRawType().getDeclaredConstructors()) { if (constructor.getAnnotation(AssistedInject.class) != null) { @SuppressWarnings("unchecked") // the constructor type and implementation type agree AssistedConstructor assistedConstructor = new AssistedConstructor( constructor, implementationType.getParameterTypes(constructor)); constructors.add(assistedConstructor); } } if (constructors.isEmpty()) { return ImmutableMap.of(); } Method[] factoryMethods = factoryType.getRawType().getMethods(); if (constructors.size() != factoryMethods.length) { throw newConfigurationException("Constructor mismatch: %s has %s @AssistedInject " + "constructors, factory %s has %s creation methods", implementationType, constructors.size(), factoryType, factoryMethods.length); } Map paramsToConstructor = Maps.newHashMap(); for (AssistedConstructor c : constructors) { if (paramsToConstructor.containsKey(c.getAssistedParameters())) { throw new RuntimeException("Duplicate constructor, " + c); } paramsToConstructor.put(c.getAssistedParameters(), c); } Map> result = Maps.newHashMap(); for (Method method : factoryMethods) { if (!method.getReturnType().isAssignableFrom(implementationType.getRawType())) { throw newConfigurationException("Return type of method %s is not assignable from %s", method, implementationType); } List parameterTypes = Lists.newArrayList(); for (TypeLiteral parameterType : factoryType.getParameterTypes(method)) { parameterTypes.add(parameterType.getType()); } ParameterListKey methodParams = new ParameterListKey(parameterTypes); if (!paramsToConstructor.containsKey(methodParams)) { throw newConfigurationException("%s has no @AssistInject constructor that takes the " + "@Assisted parameters %s in that order. @AssistInject constructors are %s", implementationType, methodParams, paramsToConstructor.values()); } method.getParameterAnnotations(); for (Annotation[] parameterAnnotations : method.getParameterAnnotations()) { for (Annotation parameterAnnotation : parameterAnnotations) { if (parameterAnnotation.annotationType() == Assisted.class) { throw newConfigurationException("Factory method %s has an @Assisted parameter, which " + "is incompatible with the deprecated @AssistedInject annotation. Please replace " + "@AssistedInject with @Inject on the %s constructor.", method, implementationType); } } } AssistedConstructor matchingConstructor = paramsToConstructor.remove(methodParams); result.put(method, matchingConstructor); } return result; } public Set> getDependencies() { List> dependencies = Lists.newArrayList(); for (AssistedConstructor constructor : factoryMethodToConstructor.values()) { for (Parameter parameter : constructor.getAllParameters()) { if (!parameter.isProvidedByFactory()) { dependencies.add(Dependency.get(parameter.getPrimaryBindingKey())); } } } return ImmutableSet.copyOf(dependencies); } public F get() { InvocationHandler invocationHandler = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] creationArgs) throws Throwable { // pass methods from Object.class to the proxy if (method.getDeclaringClass().equals(Object.class)) { return method.invoke(this, creationArgs); } AssistedConstructor constructor = factoryMethodToConstructor.get(method); Object[] constructorArgs = gatherArgsForConstructor(constructor, creationArgs); Object objectToReturn = constructor.newInstance(constructorArgs); injector.injectMembers(objectToReturn); return objectToReturn; } public Object[] gatherArgsForConstructor( AssistedConstructor constructor, Object[] factoryArgs) { int numParams = constructor.getAllParameters().size(); int argPosition = 0; Object[] result = new Object[numParams]; for (int i = 0; i < numParams; i++) { Parameter parameter = constructor.getAllParameters().get(i); if (parameter.isProvidedByFactory()) { result[i] = factoryArgs[argPosition]; argPosition++; } else { result[i] = parameter.getValue(injector); } } return result; } }; @SuppressWarnings("unchecked") // we imprecisely treat the class literal of T as a Class Class factoryRawType = (Class) factoryType.getRawType(); return factoryRawType.cast(Proxy.newProxyInstance(BytecodeGen.getClassLoader(factoryRawType), new Class[] { factoryRawType }, invocationHandler)); } private static ConfigurationException newConfigurationException(String format, Object... args) { return new ConfigurationException(ImmutableSet.of(new Message(Errors.format(format, args)))); } } guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedMethod.java0000644000175000017500000000313411463267472032470 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import com.google.inject.TypeLiteral; import com.google.inject.spi.Dependency; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Set; /** * Details about how a method in an assisted inject factory will be assisted. * * @since 3.0 * @author ramakrishna@google.com (Ramakrishna Rajanna) */ public interface AssistedMethod { /** * Returns the factory method that is being assisted. */ Method getFactoryMethod(); /** * Returns the implementation type that will be created when the method is * used. */ TypeLiteral getImplementationType(); /** * Returns the constructor that will be used to construct instances of the * implementation. */ Constructor getImplementationConstructor(); /** * Returns all non-assisted dependencies required to construct and inject * the implementation. */ Set> getDependencies(); } guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java0000644000175000017500000006470111521023104032734 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import static com.google.inject.internal.util.Iterables.getOnlyElement; import static com.google.inject.internal.util.Preconditions.checkState; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Binding; import com.google.inject.ConfigurationException; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; import com.google.inject.internal.Annotations; import com.google.inject.internal.BytecodeGen; import com.google.inject.internal.Errors; import com.google.inject.internal.ErrorsException; import com.google.inject.internal.util.Classes; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Iterables; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.Message; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import com.google.inject.spi.Toolable; import com.google.inject.util.Providers; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * The newer implementation of factory provider. This implementation uses a child injector to * create values. * * @author jessewilson@google.com (Jesse Wilson) * @author dtm@google.com (Daniel Martin) * @author schmitt@google.com (Peter Schmitt) * @author sameb@google.com (Sam Berlin) */ final class FactoryProvider2 implements InvocationHandler, ProviderWithExtensionVisitor, HasDependencies, AssistedInjectBinding { /** if a factory method parameter isn't annotated, it gets this annotation. */ static final Assisted DEFAULT_ANNOTATION = new Assisted() { public String value() { return ""; } public Class annotationType() { return Assisted.class; } @Override public boolean equals(Object o) { return o instanceof Assisted && ((Assisted) o).value().equals(""); } @Override public int hashCode() { return 127 * "value".hashCode() ^ "".hashCode(); } @Override public String toString() { return "@" + Assisted.class.getName() + "(value=)"; } }; /** All the data necessary to perform an assisted inject. */ private static class AssistData implements AssistedMethod { /** the constructor the implementation is constructed with. */ final Constructor constructor; /** the return type in the factory method that the constructor is bound to. */ final Key returnType; /** the parameters in the factory method associated with this data. */ final ImmutableList> paramTypes; /** the type of the implementation constructed */ final TypeLiteral implementationType; /** All non-assisted dependencies required by this method. */ final Set> dependencies; /** The factory method associated with this data*/ final Method factoryMethod; /** true if {@link #validForOptimizedAssistedInject} returned true. */ final boolean optimized; /** the list of optimized providers, empty if not optimized. */ final List providers; /** used to perform optimized factory creations. */ volatile Binding cachedBinding; // TODO: volatile necessary? AssistData(Constructor constructor, Key returnType, ImmutableList> paramTypes, TypeLiteral implementationType, Method factoryMethod, Set> dependencies, boolean optimized, List providers) { this.constructor = constructor; this.returnType = returnType; this.paramTypes = paramTypes; this.implementationType = implementationType; this.factoryMethod = factoryMethod; this.dependencies = dependencies; this.optimized = optimized; this.providers = providers; } @Override public String toString() { return new ToStringBuilder(getClass()) .add("ctor", constructor) .add("return type", returnType) .add("param type", paramTypes) .add("implementation type", implementationType) .add("dependencies", dependencies) .add("factory method", factoryMethod) .add("optimized", optimized) .add("providers", providers) .add("cached binding", cachedBinding) .toString(); } public Set> getDependencies() { return dependencies; } public Method getFactoryMethod() { return factoryMethod; } public Constructor getImplementationConstructor() { return constructor; } public TypeLiteral getImplementationType() { return implementationType; } } /** Mapping from method to the data about how the method will be assisted. */ private final ImmutableMap assistDataByMethod; /** the hosting injector, or null if we haven't been initialized yet */ private Injector injector; /** the factory interface, implemented and provided */ private final F factory; /** The key that this is bound to. */ private final Key factoryKey; /** * @param factoryType a Java interface that defines one or more create methods. * @param collector binding configuration that maps method return types to * implementation types. */ FactoryProvider2(Key factoryKey, BindingCollector collector) { this.factoryKey = factoryKey; TypeLiteral factoryType = factoryKey.getTypeLiteral(); Errors errors = new Errors(); @SuppressWarnings("unchecked") // we imprecisely treat the class literal of T as a Class Class factoryRawType = (Class) factoryType.getRawType(); try { if(!factoryRawType.isInterface()) { throw errors.addMessage("%s must be an interface.", factoryRawType).toException(); } ImmutableMap.Builder assistDataBuilder = ImmutableMap.builder(); // TODO: also grab methods from superinterfaces for (Method method : factoryRawType.getMethods()) { TypeLiteral returnTypeLiteral = factoryType.getReturnType(method); Key returnType; try { returnType = Annotations.getKey(returnTypeLiteral, method, method.getAnnotations(), errors); } catch(ConfigurationException ce) { // If this was an error due to returnTypeLiteral not being specified, rephrase // it as our factory not being specified, so it makes more sense to users. if(isTypeNotSpecified(returnTypeLiteral, ce)) { throw errors.keyNotFullySpecified(TypeLiteral.get(factoryRawType)).toException(); } else { throw ce; } } validateFactoryReturnType(errors, returnType.getTypeLiteral().getRawType(), factoryRawType); List> params = factoryType.getParameterTypes(method); Annotation[][] paramAnnotations = method.getParameterAnnotations(); int p = 0; List> keys = Lists.newArrayList(); for (TypeLiteral param : params) { Key paramKey = Annotations.getKey(param, method, paramAnnotations[p++], errors); Class underlylingType = paramKey.getTypeLiteral().getRawType(); if (underlylingType.equals(Provider.class) || underlylingType.equals(javax.inject.Provider.class)) { errors.addMessage("A Provider may not be a type in a factory method of an AssistedInject." + "\n Offending instance is parameter [%s] with key [%s] on method [%s]", p, paramKey, method); } keys.add(assistKey(method, paramKey, errors)); } ImmutableList> immutableParamList = ImmutableList.copyOf(keys); // try to match up the method to the constructor TypeLiteral implementation = collector.getBindings().get(returnType); if(implementation == null) { implementation = returnType.getTypeLiteral(); } InjectionPoint ctorInjectionPoint; try { ctorInjectionPoint = findMatchingConstructorInjectionPoint(method, returnType, implementation, immutableParamList); } catch(ErrorsException ee) { errors.merge(ee.getErrors()); continue; } Constructor constructor = (Constructor)ctorInjectionPoint.getMember(); List providers = Collections.emptyList(); Set> deps = getDependencies(ctorInjectionPoint, implementation); boolean optimized = false; // Now go through all dependencies of the implementation and see if it is OK to // use an optimized form of assistedinject2. The optimized form requires that // all injections directly inject the object itself (and not a Provider of the object, // or an Injector), because it caches a single child injector and mutates the Provider // of the arguments in a ThreadLocal. if(isValidForOptimizedAssistedInject(deps)) { ImmutableList.Builder providerListBuilder = ImmutableList.builder(); for(int i = 0; i < params.size(); i++) { providerListBuilder.add(new ThreadLocalProvider()); } providers = providerListBuilder.build(); optimized = true; } assistDataBuilder.put(method, new AssistData(constructor, returnType, immutableParamList, implementation, method, removeAssistedDeps(deps), optimized, providers)); } // If we generated any errors (from finding matching constructors, for instance), throw an exception. if(errors.hasErrors()) { throw errors.toException(); } assistDataByMethod = assistDataBuilder.build(); } catch (ErrorsException e) { throw new ConfigurationException(e.getErrors().getMessages()); } factory = factoryRawType.cast(Proxy.newProxyInstance(BytecodeGen.getClassLoader(factoryRawType), new Class[] { factoryRawType }, this)); } public F get() { return factory; } public Set> getDependencies() { Set> combinedDeps = new HashSet>(); for(AssistData data : assistDataByMethod.values()) { combinedDeps.addAll(data.dependencies); } return ImmutableSet.copyOf(combinedDeps); } public Key getKey() { return factoryKey; } // safe cast because values are typed to AssistedData, which is an AssistedMethod @SuppressWarnings("unchecked") public Collection getAssistedMethods() { return (Collection)assistDataByMethod.values(); } @SuppressWarnings("unchecked") public V acceptExtensionVisitor(BindingTargetVisitor visitor, ProviderInstanceBinding binding) { if (visitor instanceof AssistedInjectTargetVisitor) { return ((AssistedInjectTargetVisitor)visitor).visit((AssistedInjectBinding)this); } return visitor.visit(binding); } private void validateFactoryReturnType(Errors errors, Class returnType, Class factoryType) { if (Modifier.isPublic(factoryType.getModifiers()) && !Modifier.isPublic(returnType.getModifiers())) { errors.addMessage("%s is public, but has a method that returns a non-public type: %s. " + "Due to limitations with java.lang.reflect.Proxy, this is not allowed. " + "Please either make the factory non-public or the return type public.", factoryType, returnType); } } /** * Returns true if the ConfigurationException is due to an error of TypeLiteral not being fully * specified. */ private boolean isTypeNotSpecified(TypeLiteral typeLiteral, ConfigurationException ce) { Collection messages = ce.getErrorMessages(); if (messages.size() == 1) { Message msg = Iterables.getOnlyElement( new Errors().keyNotFullySpecified(typeLiteral).getMessages()); return msg.getMessage().equals(Iterables.getOnlyElement(messages).getMessage()); } else { return false; } } /** * Finds a constructor suitable for the method. If the implementation contained any constructors * marked with {@link AssistedInject}, this requires all {@link Assisted} parameters to exactly * match the parameters (in any order) listed in the method. Otherwise, if no * {@link AssistedInject} constructors exist, this will default to looking for an * {@literal @}{@link Inject} constructor. */ private InjectionPoint findMatchingConstructorInjectionPoint( Method method, Key returnType, TypeLiteral implementation, List> paramList) throws ErrorsException { Errors errors = new Errors(method); if(returnType.getTypeLiteral().equals(implementation)) { errors = errors.withSource(implementation); } else { errors = errors.withSource(returnType).withSource(implementation); } Class rawType = implementation.getRawType(); if (Modifier.isInterface(rawType.getModifiers())) { errors.addMessage( "%s is an interface, not a concrete class. Unable to create AssistedInject factory.", implementation); throw errors.toException(); } else if (Modifier.isAbstract(rawType.getModifiers())) { errors.addMessage( "%s is abstract, not a concrete class. Unable to create AssistedInject factory.", implementation); throw errors.toException(); } else if (Classes.isInnerClass(rawType)) { errors.cannotInjectInnerClass(rawType); throw errors.toException(); } Constructor matchingConstructor = null; boolean anyAssistedInjectConstructors = false; // Look for AssistedInject constructors... for (Constructor constructor : rawType.getDeclaredConstructors()) { if (constructor.isAnnotationPresent(AssistedInject.class)) { anyAssistedInjectConstructors = true; if (constructorHasMatchingParams(implementation, constructor, paramList, errors)) { if (matchingConstructor != null) { errors .addMessage( "%s has more than one constructor annotated with @AssistedInject" + " that matches the parameters in method %s. Unable to create AssistedInject factory.", implementation, method); throw errors.toException(); } else { matchingConstructor = constructor; } } } } if(!anyAssistedInjectConstructors) { // If none existed, use @Inject. try { return InjectionPoint.forConstructorOf(implementation); } catch(ConfigurationException e) { errors.merge(e.getErrorMessages()); throw errors.toException(); } } else { // Otherwise, use it or fail with a good error message. if(matchingConstructor != null) { // safe because we got the constructor from this implementation. @SuppressWarnings("unchecked") InjectionPoint ip = InjectionPoint.forConstructor( (Constructor)matchingConstructor, implementation); return ip; } else { errors.addMessage( "%s has @AssistedInject constructors, but none of them match the" + " parameters in method %s. Unable to create AssistedInject factory.", implementation, method); throw errors.toException(); } } } /** * Matching logic for constructors annotated with AssistedInject. * This returns true if and only if all @Assisted parameters in the * constructor exactly match (in any order) all @Assisted parameters * the method's parameter. */ private boolean constructorHasMatchingParams(TypeLiteral type, Constructor constructor, List> paramList, Errors errors) throws ErrorsException { List> params = type.getParameterTypes(constructor); Annotation[][] paramAnnotations = constructor.getParameterAnnotations(); int p = 0; List> constructorKeys = Lists.newArrayList(); for (TypeLiteral param : params) { Key paramKey = Annotations.getKey(param, constructor, paramAnnotations[p++], errors); constructorKeys.add(paramKey); } // Require that every key exist in the constructor to match up exactly. for (Key key : paramList) { // If it didn't exist in the constructor set, we can't use it. if (!constructorKeys.remove(key)) { return false; } } // If any keys remain and their annotation is Assisted, we can't use it. for (Key key : constructorKeys) { if (key.getAnnotationType() == Assisted.class) { return false; } } // All @Assisted params match up to the method's parameters. return true; } /** Calculates all dependencies required by the implementation and constructor. */ private Set> getDependencies(InjectionPoint ctorPoint, TypeLiteral implementation) { ImmutableSet.Builder> builder = ImmutableSet.builder(); builder.addAll(ctorPoint.getDependencies()); if (!implementation.getRawType().isInterface()) { for (InjectionPoint ip : InjectionPoint.forInstanceMethodsAndFields(implementation)) { builder.addAll(ip.getDependencies()); } } return builder.build(); } /** Return all non-assisted dependencies. */ private Set> removeAssistedDeps(Set> deps) { ImmutableSet.Builder> builder = ImmutableSet.builder(); for(Dependency dep : deps) { Class annotationType = dep.getKey().getAnnotationType(); if (annotationType == null || !annotationType.equals(Assisted.class)) { builder.add(dep); } } return builder.build(); } /** * Returns true if all dependencies are suitable for the optimized version of AssistedInject. The * optimized version caches the binding & uses a ThreadLocal Provider, so can only be applied if * the assisted bindings are immediately provided. This looks for hints that the values may be * lazily retrieved, by looking for injections of Injector or a Provider for the assisted values. */ private boolean isValidForOptimizedAssistedInject(Set> dependencies) { for (Dependency dep : dependencies) { if (isInjectorOrAssistedProvider(dep)) { return false; } } return true; } /** * Returns true if the dependency is for {@link Injector} or if the dependency * is a {@link Provider} for a parameter that is {@literal @}{@link Assisted}. */ private boolean isInjectorOrAssistedProvider(Dependency dependency) { Class annotationType = dependency.getKey().getAnnotationType(); if (annotationType != null && annotationType.equals(Assisted.class)) { // If it's assisted.. if (dependency.getKey().getTypeLiteral().getRawType().equals(Provider.class)) { // And a Provider... return true; } } else if (dependency.getKey().getTypeLiteral().getRawType().equals(Injector.class)) { // If it's the Injector... return true; } return false; } /** * Returns a key similar to {@code key}, but with an {@literal @}Assisted binding annotation. * This fails if another binding annotation is clobbered in the process. If the key already has * the {@literal @}Assisted annotation, it is returned as-is to preserve any String value. */ private Key assistKey(Method method, Key key, Errors errors) throws ErrorsException { if (key.getAnnotationType() == null) { return Key.get(key.getTypeLiteral(), DEFAULT_ANNOTATION); } else if (key.getAnnotationType() == Assisted.class) { return key; } else { errors.withSource(method).addMessage( "Only @Assisted is allowed for factory parameters, but found @%s", key.getAnnotationType()); throw errors.toException(); } } /** * At injector-creation time, we initialize the invocation handler. At this time we make sure * all factory methods will be able to build the target types. */ @Inject @Toolable void initialize(Injector injector) { if (this.injector != null) { throw new ConfigurationException(ImmutableList.of(new Message(FactoryProvider2.class, "Factories.create() factories may only be used in one Injector!"))); } this.injector = injector; for (Map.Entry entry : assistDataByMethod.entrySet()) { Method method = entry.getKey(); AssistData data = entry.getValue(); Object[] args; if(!data.optimized) { args = new Object[method.getParameterTypes().length]; Arrays.fill(args, "dummy object for validating Factories"); } else { args = null; // won't be used -- instead will bind to data.providers. } getBindingFromNewInjector(method, args, data); // throws if the binding isn't properly configured } } /** * Creates a child injector that binds the args, and returns the binding for the method's result. */ public Binding getBindingFromNewInjector(final Method method, final Object[] args, final AssistData data) { checkState(injector != null, "Factories.create() factories cannot be used until they're initialized by Guice."); final Key returnType = data.returnType; // We ignore any pre-existing binding annotation. final Key assistedReturnType = Key.get(returnType.getTypeLiteral(), Assisted.class); Module assistedModule = new AbstractModule() { @Override @SuppressWarnings("unchecked") // raw keys are necessary for the args array and return value protected void configure() { Binder binder = binder().withSource(method); int p = 0; if(!data.optimized) { for (Key paramKey : data.paramTypes) { // Wrap in a Provider to cover null, and to prevent Guice from injecting the parameter binder.bind((Key) paramKey).toProvider(Providers.of(args[p++])); } } else { for (Key paramKey : data.paramTypes) { // Bind to our ThreadLocalProviders. binder.bind((Key) paramKey).toProvider(data.providers.get(p++)); } } Constructor constructor = data.constructor; // Constructor *should* always be non-null here, // but if it isn't, we'll end up throwing a fairly good error // message for the user. if(constructor != null) { binder.bind(assistedReturnType) .toConstructor(constructor, (TypeLiteral)data.implementationType) .in(Scopes.NO_SCOPE); // make sure we erase any scope on the implementation type } } }; Injector forCreate = injector.createChildInjector(assistedModule); Binding binding = forCreate.getBinding(assistedReturnType); // If we have providers cached in data, cache the binding for future optimizations. if(data.optimized) { data.cachedBinding = binding; } return binding; } /** * When a factory method is invoked, we create a child injector that binds all parameters, then * use that to get an instance of the return type. */ public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable { if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } AssistData data = assistDataByMethod.get(method); Provider provider; if(data.cachedBinding != null) { // Try to get optimized form... provider = data.cachedBinding.getProvider(); } else { provider = getBindingFromNewInjector(method, args, data).getProvider(); } try { int p = 0; for(ThreadLocalProvider tlp : data.providers) { tlp.set(args[p++]); } return provider.get(); } catch (ProvisionException e) { // if this is an exception declared by the factory method, throw it as-is if (e.getErrorMessages().size() == 1) { Message onlyError = getOnlyElement(e.getErrorMessages()); Throwable cause = onlyError.getCause(); if (cause != null && canRethrow(method, cause)) { throw cause; } } throw e; } finally { for(ThreadLocalProvider tlp : data.providers) { tlp.remove(); } } } @Override public String toString() { return factory.getClass().getInterfaces()[0].getName(); } @Override public boolean equals(Object o) { return o == this || o == factory; } /** Returns true if {@code thrown} can be thrown by {@code invoked} without wrapping. */ static boolean canRethrow(Method invoked, Throwable thrown) { if (thrown instanceof Error || thrown instanceof RuntimeException) { return true; } for (Class declared : invoked.getExceptionTypes()) { if (declared.isInstance(thrown)) { return true; } } return false; } // not because we'll never know and this is easier than suppressing warnings. private static class ThreadLocalProvider extends ThreadLocal implements Provider { @Override protected Object initialValue() { throw new IllegalStateException( "Cannot use optimized @Assisted provider outside the scope of the constructor." + " (This should never happen. If it does, please report it.)"); } } } guice-3.0/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInject.java0000644000175000017500000000443111424772540032457 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.assistedinject; import static java.lang.annotation.ElementType.CONSTRUCTOR; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import com.google.inject.Inject; /** *

* When used in tandem with {@link FactoryModuleBuilder}, constructors annotated with * {@code @AssistedInject} indicate that multiple constructors can be injected, each with different * parameters. AssistedInject annotations should not be mixed with {@literal @}{@link Inject} * annotations. The assisted parameters must exactly match one corresponding factory method within * the factory interface, but the parameters do not need to be in the same order. Constructors * annotated with AssistedInject are created by Guice and receive all the benefits * (such as AOP). * *

* Obsolete Usage: When used in tandem with {@link FactoryProvider}, constructors * annotated with {@code @AssistedInject} trigger a "backwards compatibility mode". The assisted * parameters must exactly match one corresponding factory method within the factory interface and * all must be in the same order as listed in the factory. In this backwards compatable mode, * constructors annotated with AssistedInject are not created by Guice and thus receive * none of the benefits. * *

* Constructor parameters must be either supplied by the factory interface and marked with * @Assisted, or they must be injectable. * * @author jmourits@google.com (Jerome Mourits) * @author jessewilson@google.com (Jesse Wilson) */ @Target( { CONSTRUCTOR }) @Retention(RUNTIME) public @interface AssistedInject { } guice-3.0/extensions/grapher/0000755000175000017500000000000011542727756016213 5ustar drazzibdrazzibguice-3.0/extensions/grapher/build/0000755000175000017500000000000011542727756017312 5ustar drazzibdrazzibguice-3.0/extensions/grapher/build/META-INF/0000755000175000017500000000000011542727756020452 5ustar drazzibdrazzibguice-3.0/extensions/grapher/build/META-INF/MANIFEST.MF0000644000175000017500000000126511542727754022106 0ustar drazzibdrazzibManifest-Version: 1.0 Export-Package: com.google.inject.grapher.graphviz;version="1.3",com.g oogle.inject.grapher;version="1.3" Bundle-Name: guice-grapher Created-By: 1.6.0_23 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-Copyright: Copyright (C) 2006 Google Inc. Bundle-Vendor: Google, Inc. Fragment-Host: com.google.inject Bundle-Version: 3.0 Bundle-ManifestVersion: 2 Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-Description: Guice is a lightweight dependency injection framew ork for Java 5 and above Bundle-DocURL: http://code.google.com/p/google-guice/ Bundle-SymbolicName: com.google.inject.grapher guice-3.0/extensions/grapher/build/dist/0000755000175000017500000000000011542727756020255 5ustar drazzibdrazzibguice-3.0/extensions/grapher/build/classes/0000755000175000017500000000000011542727756020747 5ustar drazzibdrazzibguice-3.0/extensions/grapher/build/classes/com/0000755000175000017500000000000011542727756021525 5ustar drazzibdrazzibguice-3.0/extensions/grapher/build/classes/com/google/0000755000175000017500000000000011542727756023001 5ustar drazzibdrazzibguice-3.0/extensions/grapher/build/classes/com/google/inject/0000755000175000017500000000000011542727756024255 5ustar drazzibdrazzibguice-3.0/extensions/grapher/build/classes/com/google/inject/grapher/0000755000175000017500000000000011542727756025705 5ustar drazzibdrazzibguice-3.0/extensions/grapher/build/classes/com/google/inject/grapher/graphviz/0000755000175000017500000000000011542727756027537 5ustar drazzibdrazzibguice-3.0/extensions/grapher/pom.xml0000644000175000017500000000220011460132762017504 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-grapher Google Guice - Extensions - Grapher com.google.inject.extensions guice-assistedinject ${project.version} com.google.inject.extensions guice-multibindings ${project.version} org.easymock easymock 3.0 test guice-3.0/extensions/grapher/build.xml0000644000175000017500000000124211461503340020010 0ustar drazzibdrazzib guice-3.0/extensions/grapher/grapher.iml0000644000175000017500000000130411214265012020316 0ustar drazzibdrazzib guice-3.0/extensions/grapher/build.properties0000644000175000017500000000023111461376774021424 0ustar drazzibdrazziblib.dir=../../lib src.dir=src test.dir=test build.dir=build test.class=com.google.inject.grapher.AllTests module=com.google.inject.grapher fragment=true guice-3.0/extensions/grapher/test/0000755000175000017500000000000011214265010017142 5ustar drazzibdrazzibguice-3.0/extensions/grapher/test/com/0000755000175000017500000000000011214265010017720 5ustar drazzibdrazzibguice-3.0/extensions/grapher/test/com/google/0000755000175000017500000000000011214265010021174 5ustar drazzibdrazzibguice-3.0/extensions/grapher/test/com/google/inject/0000755000175000017500000000000011214265010022450 5ustar drazzibdrazzibguice-3.0/extensions/grapher/test/com/google/inject/grapher/0000755000175000017500000000000011526703256024117 5ustar drazzibdrazzibguice-3.0/extensions/grapher/test/com/google/inject/grapher/ShortNameFactoryTest.java0000644000175000017500000001444011413604602031043 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import static java.lang.annotation.RetentionPolicy.RUNTIME; import com.google.inject.AbstractModule; import com.google.inject.BindingAnnotation; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Provides; import com.google.inject.TypeLiteral; import com.google.inject.internal.ProviderMethod; import com.google.inject.internal.util.StackTraceElements; import com.google.inject.name.Names; import com.google.inject.spi.DefaultBindingTargetVisitor; import com.google.inject.spi.ProviderInstanceBinding; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.reflect.Member; import junit.framework.TestCase; /** * Tests for {@link ShortNameFactory}. * * @author phopkins@gmail.com (Pete Hopkins) */ public class ShortNameFactoryTest extends TestCase { // Helper objects are up here because their line numbers are tested below. private static class Obj { @Annotated public String field; Obj() {} void method(String parameter) {} } private static class ToStringObj { @Override public String toString() { return "I'm a ToStringObj"; } } @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation private @interface Annotated {} private NameFactory nameFactory; @Override protected void setUp() throws Exception { super.setUp(); nameFactory = new ShortNameFactory(); } public void testGetMemberName_field() throws Exception { Member field = Obj.class.getDeclaredField("field"); assertEquals("field", nameFactory.getMemberName(field)); } public void testGetMemberName_method() throws Exception { Member method = Obj.class.getDeclaredMethod("method", String.class); assertEquals("#method(...)", nameFactory.getMemberName(method)); } public void testGetMemberName_constructor() throws Exception { Member constructor = Obj.class.getDeclaredConstructor(); assertEquals("", nameFactory.getMemberName(constructor)); } public void testGetAnnotationName_annotationType() throws Exception { Key key = Key.get(String.class, Annotated.class); assertEquals("@Annotated", nameFactory.getAnnotationName(key)); } public void testGetAnnotationName_annotationInstance() throws Exception { Key key = Key.get(String.class, Obj.class.getDeclaredField("field").getDeclaredAnnotations()[0]); assertEquals("@Annotated", nameFactory.getAnnotationName(key)); } public void testGetAnnotationName_annotationInstanceWithParameters() throws Exception { Key key = Key.get(String.class, Names.named("name")); assertEquals("@Named(value=name)", nameFactory.getAnnotationName(key)); } public void testGetClassName_key() throws Exception { Key key = Key.get(Obj.class); assertEquals("Class name should not have the package", "ShortNameFactoryTest$Obj", nameFactory.getClassName(key)); } public void testGetClassName_keyWithTypeParameters() throws Exception { Key key = Key.get(new TypeLiteral>() {}); assertEquals("Class name and type values should not have packages", "Provider", nameFactory.getClassName(key)); } /** * Tests the case where a provider method is the source of the * @throws Exception */ public void testGetSourceName_method() throws Exception { Member method = Obj.class.getDeclaredMethod("method", String.class); assertEquals("Method should be identified by its file name and line number", "ShortNameFactoryTest.java:53", nameFactory.getSourceName(method)); } public void testGetSourceName_stackTraceElement() throws Exception { StackTraceElement element = (StackTraceElement) StackTraceElements.forMember(Obj.class.getField("field")); assertEquals("Stack trace element should be identified by its file name and line number", "ShortNameFactoryTest.java:52", nameFactory.getSourceName(element)); } public void testGetInstanceName_defaultToString() throws Exception { assertEquals("Should use class name instead of Object#toString()", "ShortNameFactoryTest$Obj", nameFactory.getInstanceName(new Obj())); } public void testGetInstanceName_customToString() throws Exception { assertEquals("Should use class's toString() method since it's defined", "I'm a ToStringObj", nameFactory.getInstanceName(new ToStringObj())); } public void testGetInstanceName_string() throws Exception { assertEquals("String should have quotes to evoke a string literal", "\"My String Instance\"", nameFactory.getInstanceName("My String Instance")); } public void testGetInstanceName_providerMethod() throws Exception { final ProviderMethod[] methodHolder = new ProviderMethod[1]; Injector injector = Guice.createInjector(new ProvidingModule()); injector.getBinding(Integer.class).acceptTargetVisitor( new DefaultBindingTargetVisitor() { @SuppressWarnings("unchecked") @Override public Void visit(ProviderInstanceBinding binding) { methodHolder[0] = (ProviderMethod) binding.getProviderInstance(); return null; } }); assertEquals("Method provider should pretty print as the method signature", "#provideInteger(String)", nameFactory.getInstanceName(methodHolder[0])); } private static class ProvidingModule extends AbstractModule { @Override protected void configure() {} @Provides public Integer provideInteger(String string) { return Integer.valueOf(string); } } } guice-3.0/extensions/grapher/test/com/google/inject/grapher/GraphingVisitorTest.java0000644000175000017500000001416611413604602030737 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import com.google.inject.spi.ConstructorBinding; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.InstanceBinding; import java.util.Collection; import java.util.List; import java.util.Set; import junit.framework.TestCase; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; /** * Tests for {@link GraphingVisitor}. * * @author phopkins@gmail.com (Pete Hopkins) */ public class GraphingVisitorTest extends TestCase { private NodeIdFactory nodeIdFactory; private InterfaceNode.Factory> interfaceNodeFactory; private ImplementationNode.Factory> implementationNodeFactory; private BindingEdge.Factory> bindingEdgeFactory; private DependencyEdge.Factory> dependencyEdgeFactory; private NodeAliasFactory nodeAliasFactory; private GraphingVisitor, ImplementationNode, BindingEdge, DependencyEdge> graphingVisitor; private List mocks; @SuppressWarnings("unchecked") @Override protected void setUp() throws Exception { super.setUp(); mocks = Lists.newArrayList(); nodeIdFactory = new StringNodeIdFactory(); interfaceNodeFactory = recordMock(createMock(InterfaceNode.Factory.class)); implementationNodeFactory = recordMock(createMock(ImplementationNode.Factory.class)); bindingEdgeFactory = recordMock(createMock(BindingEdge.Factory.class)); dependencyEdgeFactory = new DependencyEdgeFactory(); nodeAliasFactory = recordMock(createMock(NodeAliasFactory.class)); graphingVisitor = new GraphingVisitor, ImplementationNode, BindingEdge, DependencyEdge>( nodeIdFactory, interfaceNodeFactory, implementationNodeFactory, bindingEdgeFactory, dependencyEdgeFactory, nodeAliasFactory); } private T recordMock(T mock) { mocks.add(mock); return mock; } public void testNewDependencies_withInjectionPoints() throws Exception { @SuppressWarnings("unchecked") ImplementationNode node = recordMock(createMock(ImplementationNode.class)); node.addMember(Obj.class.getDeclaredField("string")); expectLastCall(); node.addMember(Obj.class.getDeclaredField("integer")); expectLastCall(); node.addMember(Obj.class.getDeclaredField("bool")); expectLastCall(); node.addMember(Obj.class.getDeclaredMethod("setInteger", Integer.class)); expectLastCall(); replayAll(); Injector injector = Guice.createInjector(new ClassModule()); ConstructorBinding binding = (ConstructorBinding) injector.getBinding(Obj.class); Collection> edges = graphingVisitor.newDependencyEdges("", node, binding.getDependencies()); assertEquals("There should be four edges, from the three fields plus the method", 4, edges.size()); verifyAll(); } public void testNewDependencies_withDependencies() throws Exception { @SuppressWarnings("unchecked") ImplementationNode node = recordMock(createMock(ImplementationNode.class)); // No members should be added to the node, since the stated dependencies // have no associated {@link InjectionPoint}s. replayAll(); Injector injector = Guice.createInjector(new ClassModule(), new InstanceModule()); InstanceBinding binding = (InstanceBinding) injector.getBinding(Obj.class); Collection> edges = graphingVisitor.newDependencyEdges("", node, binding.getDependencies()); assertEquals("One edge should be created, for the one stated Integer dependency", 1, edges.size()); verifyAll(); } private void replayAll() { for (Object mock : mocks) { replay(mock); } } private void verifyAll() { for (Object mock : mocks) { verify(mock); } } private class DependencyEdgeFactory implements DependencyEdge.Factory> { public DependencyEdge newDependencyEdge(String fromId, InjectionPoint fromPoint, String toId) { @SuppressWarnings("unchecked") DependencyEdge edge = createMock(DependencyEdge.class); return edge; } } private static class ClassModule extends AbstractModule { @Override protected void configure() { bind(String.class).toInstance("String"); bind(Integer.class).toInstance(Integer.valueOf(8)); bind(Boolean.class).toInstance(Boolean.TRUE); } } private static class InstanceModule extends AbstractModule { @Override protected void configure() { bind(Obj.class).toInstance(new Obj()); } } private static class Obj implements HasDependencies { @Inject String string; @Inject Integer integer; @Inject Boolean bool; @Inject void setInteger(Integer integer) {} public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(Key.get(Integer.class))); } } } guice-3.0/extensions/grapher/test/com/google/inject/grapher/InjectorGrapherTest.java0000644000175000017500000001031711526703312030703 0ustar drazzibdrazzib// Copyright 2011 Google Inc. All Rights Reserved. package com.google.inject.grapher; import com.google.inject.AbstractModule; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provides; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Sets; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.ConstructorBinding; import com.google.inject.spi.ConvertedConstantBinding; import com.google.inject.spi.ExposedBinding; import com.google.inject.spi.InstanceBinding; import com.google.inject.spi.LinkedKeyBinding; import com.google.inject.spi.ProviderBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderKeyBinding; import com.google.inject.spi.UntargettedBinding; import java.util.Collection; import java.util.Set; import junit.framework.TestCase; /** * Tests for {@link InjectorGrapher}. * * @author bojand@google.com (Bojan Djordjevic) */ public class InjectorGrapherTest extends TestCase { private static class FakeGraphingVisitor implements BindingTargetVisitor { private final Set keys = Sets.newHashSet(); public Void visit(InstanceBinding binding) { return record(binding); } public Void visit(ProviderInstanceBinding binding) { return record(binding); } public Void visit(ProviderKeyBinding binding) { return record(binding); } public Void visit(LinkedKeyBinding binding) { return record(binding); } public Void visit(ExposedBinding binding) { return record(binding); } public Void visit(UntargettedBinding binding) { return record(binding); } public Void visit(ConstructorBinding binding) { return record(binding); } public Void visit(ConvertedConstantBinding binding) { return record(binding); } public Void visit(ProviderBinding binding) { return record(binding); } public Set getKeys() { return keys; } private Void record(Binding binding) { keys.add(binding.getKey()); return null; } } private static class A {} private static class B {} private static class C {} private static class D {} private static class E {} private static class ClassModule extends AbstractModule { @Override protected void configure() { bind(D.class).toInstance(new D()); bind(E.class).toInstance(new E()); } @Provides A provideA(B b, @Named("test") C c) { return new A(); } @Provides B provideB(D d, E e) { return new B(); } @Provides @Named("test") C provideC(D d, E e) { return new C(); } } private final BindingTargetVisitor>> keyVisitor = new TransitiveDependencyVisitor(); private final Renderer renderer = new Renderer() { public void render() {} }; private FakeGraphingVisitor graphingVisitor; private Injector injector; private InjectorGrapher grapher; @Override protected void setUp() throws Exception { super.setUp(); graphingVisitor = new FakeGraphingVisitor(); injector = Guice.createInjector(new ClassModule()); grapher = new InjectorGrapher(keyVisitor, graphingVisitor, renderer); } /** Tests making a graph rooted at a {@link Class}. */ public void testRootedAtClass() throws Exception { grapher.of(injector) .rootedAt(B.class) .graph(); assertEquals(ImmutableSet.>of( Key.get(B.class), Key.get(D.class), Key.get(E.class)), graphingVisitor.getKeys()); } /** Tests making a graph rooted at a {@link Key}. */ public void testRootedAtKey() throws Exception { Key cKey = Key.get(C.class, Names.named("test")); grapher.of(injector) .rootedAt(cKey) .graph(); assertEquals(ImmutableSet.of( cKey, Key.get(D.class), Key.get(E.class)), graphingVisitor.getKeys()); } }guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/0000755000175000017500000000000011214265010025024 5ustar drazzibdrazzibguice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/DeLorian.java0000644000175000017500000000176211214265010027372 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.Inject; import com.google.inject.Provider; class DeLorian { // We @Inject a Provider to demonstrate that the graph doesn't differentiate // between a Provider and just @Injecting T. @Inject @Driver Provider driver; @Inject FluxCapacitor fluxCapacitor; @Inject public void setEnergySource(EnergySource energySource) {} }guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/PinballParts.java0000644000175000017500000000162211214265010030263 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.Inject; import com.google.inject.Provider; class PinballParts { // Shows up as an injection point on an instance. We use a Provider so that // it doesn't have to be satisfied when the Injector is created. @Inject Provider salvager; } guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/EnergySource.java0000644000175000017500000000134511214265010030304 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.ProvidedBy; @ProvidedBy(EnergySourceProvider.class) interface EnergySource {}guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/EnergySourceProvider.java0000644000175000017500000000205311214265010032014 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.name.Named; class EnergySourceProvider implements Provider { @Inject void setSources(@Nuclear EnergySource nuclear, @Renewable EnergySource renewable) {} // This will demonstrate a ConvertedConstantBinding. @Inject void setYear(@Named("year") int year) {} public EnergySource get() { return null; } } guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/Driver.java0000644000175000017500000000174211214265010027126 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import com.google.inject.BindingAnnotation; @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation @interface Driver {}guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/AssistedInjectModule.java0000644000175000017500000000213711214265010031754 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.AbstractModule; import com.google.inject.assistedinject.FactoryProvider; /** * Module to add {@link AssistedInject}-based elements to the demo * {@link Injector}. * * @author phopkins@gmail.com (Pete Hopkins) */ public class AssistedInjectModule extends AbstractModule { @Override protected void configure() { bind(DancePartyFactory.class).toProvider( FactoryProvider.newFactory(DancePartyFactory.class, DancePartyImpl.class)); } } guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/BackToTheFutureModule.java0000644000175000017500000000342511214265010032040 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.Singleton; import com.google.inject.name.Names; /** * Module that adds a variety of different kinds of {@link Bindings} to be used * to generate a comprehensive sample graph. * * @see InjectorGrapherDemo * * @author phopkins@gmail.com (Pete Hopkins) */ public class BackToTheFutureModule extends AbstractModule { @Override protected void configure() { bind(DeLorian.class); bind(EnergySource.class).annotatedWith(Nuclear.class).to(Plutonium.class); bind(EnergySource.class).annotatedWith(Renewable.class).to(Lightning.class); bind(Plutonium.class).toProvider(PlutoniumProvider.class); bind(PinballParts.class).annotatedWith(Used.class).toInstance(new PinballParts()); bind(Person.class).annotatedWith(Driver.class).to(MartyMcFly.class).in(Singleton.class); bind(Person.class).annotatedWith(Inventor.class).to(DocBrown.class).in(Singleton.class); bindConstant().annotatedWith(Names.named("year")).to("1955"); } @Provides public FluxCapacitor provideFluxCapacitor(EnergySource energySource) { return null; } }guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/Inventor.java0000644000175000017500000000174411214265010027501 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import com.google.inject.BindingAnnotation; @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation @interface Inventor {}guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/MultibinderModule.java0000644000175000017500000000221511214265010031313 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.AbstractModule; import com.google.inject.multibindings.Multibinder; /** * Module to add {@link Multibinder}-based bindings to the injector. * * @author phopkins@gmail.com (Pete Hopkins) */ public class MultibinderModule extends AbstractModule { @Override protected void configure() { Multibinder charactersBinder = Multibinder.newSetBinder(binder(), Person.class); charactersBinder.addBinding().to(MartyMcFly.class); charactersBinder.addBinding().to(DocBrown.class); } } guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/FluxCapacitor.java0000644000175000017500000000122411214265010030432 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; class FluxCapacitor {}guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/MartyMcFly.java0000644000175000017500000000124311214265010027716 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; class MartyMcFly implements Person {}guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/Used.java0000644000175000017500000000174011214265010026571 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import com.google.inject.BindingAnnotation; @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation @interface Used {}guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/DancePartyFactory.java0000644000175000017500000000147511214265010031260 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; /** * Interface to be used with {@link FactoryProvider}. * * @author phopkins@gmail.com (Pete Hopkins) */ interface DancePartyFactory { DanceParty newDanceParty(String thatNewSound); } guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/Person.java0000644000175000017500000000122111214265010027131 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; interface Person {}guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/Lightning.java0000644000175000017500000000143611214265010027616 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.Inject; import com.google.inject.name.Named; class Lightning implements EnergySource { @Inject @Named("year") String yearOfStrike; }guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/Nuclear.java0000644000175000017500000000174311214265010027265 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import com.google.inject.BindingAnnotation; @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation @interface Nuclear {}guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/DocBrown.java0000644000175000017500000000141511214265010027405 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.Inject; class DocBrown implements Person { // handy because it introduces a cycle @Inject DeLorian stylishCar; } guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/Renewable.java0000644000175000017500000000174511214265010027602 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import com.google.inject.BindingAnnotation; @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation @interface Renewable {}guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/DanceParty.java0000644000175000017500000000122611214265010027722 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; interface DanceParty {} guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/DancePartyImpl.java0000644000175000017500000000153311214265010030545 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; class DancePartyImpl implements DanceParty { @Inject public DancePartyImpl(@Assisted String thatNewSound, MartyMcFly guitarist) {} } guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/PlutoniumProvider.java0000644000175000017500000000161211214265010031376 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.Inject; import com.google.inject.Provider; class PlutoniumProvider implements Provider { @Inject public PlutoniumProvider(@Inventor Person inventor, @Used PinballParts parts) {} public Plutonium get() { return null; } } guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/InjectorGrapherDemo.java0000644000175000017500000000355511214265010031572 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Stage; import com.google.inject.grapher.GrapherModule; import com.google.inject.grapher.InjectorGrapher; import com.google.inject.grapher.graphviz.GraphvizModule; import com.google.inject.grapher.graphviz.GraphvizRenderer; import java.io.File; import java.io.PrintWriter; /** * Application that instantiates {@link BackToTheFutureModule} and graphs it, * writing the output to a DOT-formatted file (filename specified on the * command line). * * @author phopkins@gmail.com (Pete Hopkins) */ public class InjectorGrapherDemo { public static void main(String[] args) throws Exception { // TODO(phopkins): Switch to Stage.TOOL when issue 297 is fixed. Injector demoInjector = Guice.createInjector(Stage.DEVELOPMENT, new BackToTheFutureModule(), new MultibinderModule()); PrintWriter out = new PrintWriter(new File(args[0]), "UTF-8"); Injector injector = Guice.createInjector(new GrapherModule(), new GraphvizModule()); GraphvizRenderer renderer = injector.getInstance(GraphvizRenderer.class); renderer.setOut(out).setRankdir("TB"); injector.getInstance(InjectorGrapher.class) .of(demoInjector) .graph(); } } guice-3.0/extensions/grapher/test/com/google/inject/grapher/demo/Plutonium.java0000644000175000017500000000125011214265010027661 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.demo; class Plutonium implements EnergySource {}guice-3.0/extensions/grapher/test/com/google/inject/grapher/TransitiveDependencyVisitorTest.java0000644000175000017500000001645611413604602033333 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.AbstractModule; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.name.Names; import com.google.inject.spi.ConstructorBinding; import com.google.inject.spi.ConvertedConstantBinding; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InstanceBinding; import com.google.inject.spi.LinkedKeyBinding; import com.google.inject.spi.ProviderBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderKeyBinding; import java.util.Collection; import java.util.Set; import junit.framework.TestCase; /** * Tests for {@link TransitiveDependencyVisitor}. * * @author phopkins@gmail.com (Pete Hopkins) */ public class TransitiveDependencyVisitorTest extends TestCase { private TransitiveDependencyVisitor visitor; @Override protected void setUp() throws Exception { super.setUp(); visitor = new TransitiveDependencyVisitor(); } public void testVisitConstructor() { Binding binding = getBinding(Key.get(ConstructedClass.class)); Collection> dependencies = visitor.visit((ConstructorBinding) binding); assertDependencies(dependencies, Key.get(A.class), Key.get(B.class), Key.get(C.class), Key.get(D.class)); } public void testVisitConvertedConstant() { Binding binding = getBinding(Key.get(Integer.class, Names.named("number")), new ConvertedConstantModule()); Collection> dependencies = visitor.visit( (ConvertedConstantBinding) binding); assertDependencies(dependencies, Key.get(String.class, Names.named("number"))); } public void testVisitInstance() { Binding binding = getBinding(Key.get(ConstructedClass.class), new InstanceModule()); Collection> dependencies = visitor.visit( (InstanceBinding) binding); // Dependencies will only be on the field- and method-injected classes. assertDependencies(dependencies, Key.get(A.class), Key.get(D.class)); } public void testVisitInstance_instanceHasDependencies() { Binding binding = getBinding(Key.get(Interface.class), new HasDependenciesModule()); Collection> dependencies = visitor.visit( (InstanceBinding) binding); // Dependencies should only be on the stated // HasDependencies#getDependencies() values assertDependencies(dependencies, Key.get(G.class)); } public void testVisitLinkedKey() { Binding binding = getBinding(Key.get(Interface.class), new LinkedKeyModule()); Collection> dependencies = visitor.visit((LinkedKeyBinding) binding); // Dependency should be to the class this interface is bound to. assertDependencies(dependencies, Key.get(ConstructedClass.class)); } public void testVisitProviderBinding() { Binding binding = getBinding(Key.get(new TypeLiteral>() {})); Collection> dependencies = visitor.visit((ProviderBinding) binding); assertDependencies(dependencies, Key.get(ConstructedClass.class)); } public void testVisitProviderInstance() { Binding binding = getBinding(Key.get(ConstructedClass.class), new ProviderInstanceModule()); Collection> dependencies = visitor.visit( (ProviderInstanceBinding) binding); // Dependencies will only be on the field- and method-injected classes. assertDependencies(dependencies, Key.get(E.class), Key.get(F.class)); } public void testVisitProviderKey() { Binding binding = getBinding(Key.get(ConstructedClass.class), new ProviderKeyModule()); Collection> dependencies = visitor.visit((ProviderKeyBinding) binding); // Dependency should be to the class that provides this one. assertDependencies(dependencies, Key.get(ConstructedClassProvider.class)); } private Binding getBinding(Key key, Module... modules) { return Guice.createInjector(modules).getBinding(key); } private void assertDependencies(Collection> dependencies, Key... keys) { assertNotNull("Dependencies should not be null", dependencies); assertEquals("There should be " + keys.length + " dependencies", keys.length, dependencies.size()); for (Key key : keys) { assertTrue("Dependencies should contain " + key, dependencies.contains(key)); } } private static class A {} private static class B {} private static class C {} private static class D {} private static class E {} private static class F {} private static class G {} private static interface Interface {} private static class ConstructedClass implements Interface { @Inject A a; ConstructedClass() {} @Inject ConstructedClass(B b, C c) {} @Inject void setD(D d) {} } private static class ConstructedClassProvider implements Provider { @Inject E e; ConstructedClassProvider() {} @Inject ConstructedClassProvider(A a, B b, C c) {} @Inject void setF(F f) {} public ConstructedClass get() { return null; } } private static class HasDependenciesClass implements Interface, HasDependencies { @Inject A a; @Inject B b; public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(Key.get(G.class))); } } private static class ConvertedConstantModule extends AbstractModule { @Override protected void configure() { bindConstant().annotatedWith(Names.named("number")).to("2008"); } } private static class InstanceModule extends AbstractModule { @Override protected void configure() { bind(ConstructedClass.class).toInstance(new ConstructedClass()); } } private static class LinkedKeyModule extends AbstractModule { @Override protected void configure() { bind(Interface.class).to(ConstructedClass.class); } } private static class ProviderInstanceModule extends AbstractModule { @Override protected void configure() { bind(ConstructedClass.class).toProvider(new ConstructedClassProvider()); } } private static class HasDependenciesModule extends AbstractModule { @Override protected void configure() { bind(Interface.class).toInstance(new HasDependenciesClass()); } } private static class ProviderKeyModule extends AbstractModule { @Override protected void configure() { bind(ConstructedClass.class).toProvider(ConstructedClassProvider.class); } } } guice-3.0/extensions/grapher/test/com/google/inject/grapher/AllTests.java0000644000175000017500000000201311214265010026472 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import junit.framework.Test; import junit.framework.TestSuite; /** * @author phopkins@gmail.com (Pete Hopkins) */ public class AllTests { public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(GraphingVisitorTest.class); suite.addTestSuite(ShortNameFactoryTest.class); suite.addTestSuite(TransitiveDependencyVisitorTest.class); return suite; } } guice-3.0/extensions/grapher/src/0000755000175000017500000000000011214265010016752 5ustar drazzibdrazzibguice-3.0/extensions/grapher/src/com/0000755000175000017500000000000011214265010017530 5ustar drazzibdrazzibguice-3.0/extensions/grapher/src/com/google/0000755000175000017500000000000011214265010021004 5ustar drazzibdrazzibguice-3.0/extensions/grapher/src/com/google/inject/0000755000175000017500000000000011214265010022260 5ustar drazzibdrazzibguice-3.0/extensions/grapher/src/com/google/inject/grapher/0000755000175000017500000000000011413604602023715 5ustar drazzibdrazzibguice-3.0/extensions/grapher/src/com/google/inject/grapher/DependencyEdge.java0000644000175000017500000000334311461631440027431 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.internal.util.Nullable; import com.google.inject.spi.InjectionPoint; /** * Interface for an edge from a class or {@link InjectionPoint} to the * interface node that will satisfy the dependency. * * @author phopkins@gmail.com (Pete Hopkins) * * @param The type for node IDs. */ public interface DependencyEdge { /** * Factory interface for {@link DependencyEdge}s. Renderer implementations * will need to provide an implementation for this. * * @param The type for node IDs. * @param The {@link DependencyEdge} sub-type that this factory provides. */ interface Factory> { /** * Creates a new {@link DependencyEdge} and adds it to the graph. * * @param fromId The ID for the class or instance node that has the * dependency. * @param fromPoint The point where the dependency will be * {@literal @}{@link Inject}ed. * @param toId The ID for the interface node that satisfies the dependency. */ T newDependencyEdge(K fromId, @Nullable InjectionPoint fromPoint, K toId); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/0000755000175000017500000000000011413604602025547 5ustar drazzibdrazzibguice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/InterfaceNodeFactory.java0000644000175000017500000000452011214265012032446 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; import com.google.inject.Inject; import com.google.inject.Key; import com.google.inject.grapher.InterfaceNode; import com.google.inject.grapher.NameFactory; /** * Graphviz-specific implementation of {@link InterfaceNode.Factory}. Uses * a {@link GraphvizEdgeAdaptor} to delegate to a {@link GraphvizNode}. * * @author phopkins@gmail.com (Pete Hopkins) */ public class InterfaceNodeFactory implements InterfaceNode.Factory> { private final GraphvizRenderer renderer; private final NameFactory nameFactory; @Inject public InterfaceNodeFactory(GraphvizRenderer renderer, NameFactory nameFactory) { this.renderer = renderer; this.nameFactory = nameFactory; } public InterfaceNode newInterfaceNode(String nodeId) { GraphvizNode node = new GraphvizNode(nodeId); renderer.addNode(node); return newAdaptor(node); } private GraphvizNodeAdaptor newAdaptor(GraphvizNode node) { return new GraphvizNodeAdaptor(node); } /** * Adaptor class that converts {@link InterfaceNode} methods to display * operations on a {@link GraphvizNode}. */ protected class GraphvizNodeAdaptor implements InterfaceNode { protected final GraphvizNode node; public GraphvizNodeAdaptor(GraphvizNode node) { this.node = node; this.node.setStyle(NodeStyle.DASHED); } public void setKey(Key key) { String title = nameFactory.getClassName(key); node.setTitle(title); node.addSubtitle(0, nameFactory.getAnnotationName(key)); } public void setSource(Object source) { // TODO(phopkins): Show the Module on the graph, which comes from the // class name when source is a StackTraceElement. } } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizEdge.java0000644000175000017500000000531411413604602030774 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; import com.google.inject.internal.util.ImmutableList; import java.util.List; /** * Data object to encapsulate the attributes of Graphviz edges that we're * interested in drawing. * * @author phopkins@gmail.com (Pete Hopkins) */ public class GraphvizEdge { private final String headNodeId; private String headPortId; private CompassPoint headCompassPoint; private List arrowHead = ImmutableList.of(ArrowType.NORMAL); private final String tailNodeId; private String tailPortId; private CompassPoint tailCompassPoint; private List arrowTail = ImmutableList.of(ArrowType.NONE); private EdgeStyle style = EdgeStyle.SOLID; public GraphvizEdge(String tailNodeId, String headNodeId) { this.tailNodeId = tailNodeId; this.headNodeId = headNodeId; } public String getHeadNodeId() { return headNodeId; } public String getHeadPortId() { return headPortId; } public void setHeadPortId(String headPortId) { this.headPortId = headPortId; } public CompassPoint getHeadCompassPoint() { return headCompassPoint; } public void setHeadCompassPoint(CompassPoint headCompassPoint) { this.headCompassPoint = headCompassPoint; } public List getArrowHead() { return arrowHead; } public void setArrowHead(List arrowHead) { this.arrowHead = ImmutableList.copyOf(arrowHead); } public String getTailNodeId() { return tailNodeId; } public String getTailPortId() { return tailPortId; } public void setTailPortId(String tailPortId) { this.tailPortId = tailPortId; } public CompassPoint getTailCompassPoint() { return tailCompassPoint; } public void setTailCompassPoint(CompassPoint tailCompassPoint) { this.tailCompassPoint = tailCompassPoint; } public List getArrowTail() { return arrowTail; } public void setArrowTail(List arrowTail) { this.arrowTail = ImmutableList.copyOf(arrowTail); } public EdgeStyle getStyle() { return style; } public void setStyle(EdgeStyle style) { this.style = style; } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizRenderer.java0000644000175000017500000001544511413604602031704 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; import com.google.inject.grapher.ImplementationNode; import com.google.inject.grapher.NodeAliasFactory; import com.google.inject.grapher.Renderer; import com.google.inject.internal.util.Join; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Maps; import java.io.PrintWriter; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * {@link Renderer} implementation that writes out a Graphviz DOT file of the * graph. Bound in {@link GraphvizModule}. *

* Specify the {@link PrintWriter} to output to with * {@link #setOut(PrintWriter)}. * * @author phopkins@gmail.com (Pete Hopkins) */ public class GraphvizRenderer implements Renderer, NodeAliasFactory { private final List nodes = Lists.newArrayList(); private final List edges = Lists.newArrayList(); private final Map aliases = Maps.newHashMap(); private PrintWriter out; private String rankdir = "TB"; public GraphvizRenderer setOut(PrintWriter out) { this.out = out; return this; } public GraphvizRenderer setRankdir(String rankdir) { this.rankdir = rankdir; return this; } public void addNode(GraphvizNode node) { nodes.add(node); } public void addEdge(GraphvizEdge edge) { edges.add(edge); } public void newAlias(String fromId, String toId) { aliases.put(fromId, toId); } protected String resolveAlias(String id) { while (aliases.containsKey(id)) { id = aliases.get(id); } return id; } public void render() { start(); for (GraphvizNode node : nodes) { renderNode(node); } for (GraphvizEdge edge : edges) { renderEdge(edge); } finish(); out.flush(); } protected Map getGraphAttributes() { Map attrs = Maps.newHashMap(); attrs.put("rankdir", rankdir); return attrs; } protected void start() { out.println("digraph injector {"); Map attrs = getGraphAttributes(); out.println("graph " + getAttrString(attrs) + ";"); } protected void finish() { out.println("}"); } protected void renderNode(GraphvizNode node) { Map attrs = getNodeAttributes(node); out.println(node.getNodeId() + " " + getAttrString(attrs)); } protected Map getNodeAttributes(GraphvizNode node) { Map attrs = Maps.newHashMap(); attrs.put("label", getNodeLabel(node)); // remove most of the margin because the table has internal padding attrs.put("margin", "0.02,0"); attrs.put("shape", node.getShape().toString()); attrs.put("style", node.getStyle().toString()); return attrs; } /** * Creates the "label" for a node. This is a string of HTML that defines a * table with a heading at the top and (in the case of * {@link ImplementationNode}s) rows for each of the member fields. */ protected String getNodeLabel(GraphvizNode node) { String cellborder = node.getStyle() == NodeStyle.INVISIBLE ? "1" : "0"; StringBuilder html = new StringBuilder(); html.append("<"); html.append(""); html.append("").append("").append(""); for (Map.Entry field : node.getFields().entrySet()) { html.append(""); html.append("").append(""); } html.append("
"); String subtitle = Join.join("
", node.getSubtitles()); if (subtitle.length() != 0) { html.append(""); html.append(subtitle).append("
").append("
"); } html.append(""); html.append(htmlEscape(node.getTitle())).append("
"); html.append("
").append("
"); html.append(htmlEscape(field.getValue())); html.append("
"); html.append(">"); return html.toString(); } protected void renderEdge(GraphvizEdge edge) { Map attrs = getEdgeAttributes(edge); String tailId = getEdgeEndPoint(resolveAlias(edge.getTailNodeId()), edge.getTailPortId(), edge.getTailCompassPoint()); String headId = getEdgeEndPoint(resolveAlias(edge.getHeadNodeId()), edge.getHeadPortId(), edge.getHeadCompassPoint()); out.println(tailId + " -> " + headId + " " + getAttrString(attrs)); } protected Map getEdgeAttributes(GraphvizEdge edge) { Map attrs = Maps.newHashMap(); attrs.put("arrowhead", getArrowString(edge.getArrowHead())); attrs.put("arrowtail", getArrowString(edge.getArrowTail())); attrs.put("style", edge.getStyle().toString()); return attrs; } private String getAttrString(Map attrs) { List attrList = Lists.newArrayList(); for (Entry attr : attrs.entrySet()) { String value = attr.getValue(); if (value != null) { attrList.add(attr.getKey() + "=" + value); } } return "[" + Join.join(", ", attrList) + "]"; } /** * Turns a {@link List} of {@link ArrowType}s into a {@link String} that * represents combining them. With Graphviz, that just means concatenating * them. */ protected String getArrowString(List arrows) { return Join.join("", arrows); } protected String getEdgeEndPoint(String nodeId, String portId, CompassPoint compassPoint) { List portStrings = Lists.newArrayList(nodeId); if (portId != null) { portStrings.add(portId); } if (compassPoint != null) { portStrings.add(compassPoint.toString()); } return Join.join(":", portStrings); } protected String htmlEscape(String str) { return str.replace("&", "&").replace("<", "<").replace(">", ">"); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizModule.java0000644000175000017500000000457711214265012031364 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; import com.google.inject.AbstractModule; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; import com.google.inject.grapher.BindingEdge; import com.google.inject.grapher.DependencyEdge; import com.google.inject.grapher.ImplementationNode; import com.google.inject.grapher.InterfaceNode; import com.google.inject.grapher.NameFactory; import com.google.inject.grapher.NodeAliasFactory; import com.google.inject.grapher.NodeIdFactory; import com.google.inject.grapher.Renderer; import com.google.inject.grapher.ShortNameFactory; import com.google.inject.grapher.StringNodeIdFactory; /** * Module that provides {@link GraphvizRenderer} as the {@link Renderer} and * binds the other Graphviz factories. * * @author phopkins@gmail.com (Pete Hopkins) */ public class GraphvizModule extends AbstractModule { @Override protected void configure() { bind(Renderer.class).to(GraphvizRenderer.class); bind(new TypeLiteral>() {}).to(GraphvizRenderer.class); bind(GraphvizRenderer.class).in(Singleton.class); bind(NameFactory.class).to(ShortNameFactory.class); bind(new TypeLiteral>() {}).to(StringNodeIdFactory.class); bind(PortIdFactory.class).to(PortIdFactoryImpl.class); bind(new TypeLiteral>>() {}) .to(BindingEdgeFactory.class); bind(new TypeLiteral>>() {}) .to(DependencyEdgeFactory.class); bind(new TypeLiteral>>() {}) .to(InterfaceNodeFactory.class); bind(new TypeLiteral>>() {}) .to(ImplementationNodeFactory.class); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/PortIdFactory.java0000644000175000017500000000203711214265012031142 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; import com.google.inject.grapher.StringNodeIdFactory; import java.lang.reflect.Member; /** * Interface for a service that returns Graphviz port IDs, used for naming the * rows in {@link ImplementationNode}-displaying {@link GraphvizNode}s. * Implemented by {@link StringNodeIdFactory}. * * @author phopkins@gmail.com (Pete Hopkins) */ public interface PortIdFactory { String getPortId(Member member); } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/NodeShape.java0000644000175000017500000000204611214265012030257 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; /** * Enum for the shapes that are most interesting for Guice graphing. *

* See: http://www.graphviz.org/doc/info/shapes.html * * @author phopkins@gmail.com (Pete Hopkins) */ public enum NodeShape { BOX("box"), ELLIPSE("ellipse"), NONE("none"); private final String shape; NodeShape(String shape) { this.shape = shape; } @Override public String toString() { return shape; } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/DependencyEdgeFactory.java0000644000175000017500000000445611413604602032616 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; import com.google.inject.Inject; import com.google.inject.grapher.DependencyEdge; import com.google.inject.internal.util.ImmutableList; import com.google.inject.spi.InjectionPoint; /** * Graphviz-specific implementation of {@link DependencyEdge.Factory}. Uses a * {@link GraphvizEdgeAdaptor} to delegate to a {@link GraphvizEdge}. * * @author phopkins@gmail.com (Pete Hopkins) */ public class DependencyEdgeFactory implements DependencyEdge.Factory> { private final GraphvizRenderer renderer; private final PortIdFactory portIdFactory; @Inject public DependencyEdgeFactory(GraphvizRenderer renderer, PortIdFactory portIdFactory) { this.renderer = renderer; this.portIdFactory = portIdFactory; } public DependencyEdge newDependencyEdge(String fromId, InjectionPoint fromPoint, String toId) { GraphvizEdge edge = new GraphvizEdge(fromId, toId); if (fromPoint == null) { edge.setTailPortId("header"); } else { edge.setTailPortId(portIdFactory.getPortId(fromPoint.getMember())); } renderer.addEdge(edge); return newAdaptor(edge); } protected GraphvizEdgeAdaptor newAdaptor(GraphvizEdge edge) { return new GraphvizEdgeAdaptor(edge); } /** * Adaptor class that converts {@link DependencyEdge} methods to display * operations on a {@link GraphvizEdge}. */ protected class GraphvizEdgeAdaptor implements DependencyEdge { protected final GraphvizEdge edge; public GraphvizEdgeAdaptor(GraphvizEdge edge) { this.edge = edge; this.edge.setArrowHead(ImmutableList.of(ArrowType.NORMAL)); this.edge.setTailCompassPoint(CompassPoint.EAST); } } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/ArrowType.java0000644000175000017500000000250511214265012030345 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; /** * Arrow symbols that are available from Graphviz. These can be composed by * concatenation to make double arrows and such. *

* See: http://www.graphviz.org/doc/info/arrows.html * * @author phopkins@gmail.com (Pete Hopkins) */ public enum ArrowType { BOX("box"), BOX_OPEN("obox"), CROW("crow"), DIAMOND("diamond"), DIAMOND_OPEN("odiamond"), DOT("dot"), DOT_OPEN("odot"), INVERTED("inv"), INVERTED_OPEN("oinv"), NONE("none"), NORMAL("normal"), NORMAL_OPEN("onormal"), TEE("tee"), VEE("vee"); private final String arrowType; ArrowType(String arrowType) { this.arrowType = arrowType; } @Override public String toString() { return arrowType; } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/CompassPoint.java0000644000175000017500000000240111214265012031023 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; /** * Enum for the "compass point" values used to control where edge * end points appear on the graph. *

* See: http://www.graphviz.org/doc/info/attrs.html#k:portPos * * @author phopkins@gmail.com (Pete Hopkins) */ public enum CompassPoint { NORTH("n"), NORTH_EAST("ne"), EAST("e"), SOUTH_EAST("se"), SOUTH("s"), SOUTH_WEST("sw"), WEST("w"), NORTH_WEST("nw"), CENTER("c"), EXTERIOR_SIDE("_"); /** Graphviz "compass_pt" value. */ private final String compassPt; CompassPoint(String compassPt) { this.compassPt = compassPt; } @Override public String toString() { return compassPt; } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/BindingEdgeFactory.java0000644000175000017500000000444611413604602032111 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; import com.google.inject.Inject; import com.google.inject.grapher.BindingEdge; import com.google.inject.internal.util.ImmutableList; /** * Graphviz-specific implementation of {@link BindingEdge.Factory}. Uses a * {@link GraphvizEdgeAdaptor} to delegate to a {@link GraphvizEdge}. * * @author phopkins@gmail.com (Pete Hopkins) */ public class BindingEdgeFactory implements BindingEdge.Factory> { private final GraphvizRenderer renderer; @Inject public BindingEdgeFactory(GraphvizRenderer renderer) { this.renderer = renderer; } public BindingEdge newBindingEdge(String fromId, String toId) { GraphvizEdge edge = new GraphvizEdge(fromId, toId); renderer.addEdge(edge); return newAdaptor(edge); } protected GraphvizEdgeAdaptor newAdaptor(GraphvizEdge edge) { return new GraphvizEdgeAdaptor(edge); } /** * Adaptor class that converts {@link BindingEdge} methods to display * operations on a {@link GraphvizEdge}. */ protected class GraphvizEdgeAdaptor implements BindingEdge { protected final GraphvizEdge edge; public GraphvizEdgeAdaptor(GraphvizEdge edge) { this.edge = edge; this.edge.setStyle(EdgeStyle.DASHED); } public void setType(BindingEdge.Type type) { switch (type) { case NORMAL: edge.setArrowHead(ImmutableList.of(ArrowType.NORMAL_OPEN)); break; case PROVIDER: edge.setArrowHead(ImmutableList.of(ArrowType.NORMAL_OPEN, ArrowType.NORMAL_OPEN)); break; case CONVERTED_CONSTANT: edge.setArrowHead(ImmutableList.of(ArrowType.NORMAL_OPEN, ArrowType.DOT_OPEN)); break; } } } }guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/GraphvizNode.java0000644000175000017500000000526011413604602031015 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.Maps; import java.util.List; import java.util.Map; /** * Data object to encapsulate the attributes of Graphviz nodes that we're * interested in drawing. * * @author phopkins@gmail.com (Pete Hopkins) */ public class GraphvizNode { private final String nodeId; private NodeStyle style = NodeStyle.SOLID; private NodeShape shape = NodeShape.BOX; private String title = ""; private Map subtitles = Maps.newTreeMap(); private String headerTextColor = "#000000"; private String headerBackgroundColor = "#ffffff"; /** {@link Map} from port ID to field title */ private Map fields = Maps.newLinkedHashMap(); public GraphvizNode(String nodeId) { this.nodeId = nodeId; } public String getNodeId() { return nodeId; } public NodeShape getShape() { return shape; } public void setShape(NodeShape shape) { this.shape = shape; } public NodeStyle getStyle() { return style; } public void setStyle(NodeStyle style) { this.style = style; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public List getSubtitles() { return ImmutableList.copyOf(subtitles.values()); } public void addSubtitle(int position, String subtitle) { this.subtitles.put(position, subtitle); } public String getHeaderTextColor() { return headerTextColor; } public void setHeaderTextColor(String headerTextColor) { this.headerTextColor = headerTextColor; } public String getHeaderBackgroundColor() { return headerBackgroundColor; } public void setHeaderBackgroundColor(String headerBackgroundColor) { this.headerBackgroundColor = headerBackgroundColor; } public void addField(String portId, String title) { fields.put(portId, title); } public Map getFields() { return ImmutableMap.copyOf(fields); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/ImplementationNodeFactory.java0000644000175000017500000000561011214265012033534 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; import com.google.inject.Inject; import com.google.inject.Key; import com.google.inject.grapher.ImplementationNode; import com.google.inject.grapher.NameFactory; import com.google.inject.grapher.graphviz.BindingEdgeFactory.GraphvizEdgeAdaptor; import java.lang.reflect.Member; /** * Graphviz-specific implementation of {@link ImplementationNode.Factory}. Uses * a {@link GraphvizEdgeAdaptor} to delegate to a {@link GraphvizNode}. * * @author phopkins@gmail.com (Pete Hopkins) */ public class ImplementationNodeFactory implements ImplementationNode.Factory> { private final GraphvizRenderer renderer; private final NameFactory nameFactory; private final PortIdFactory portIdFactory; @Inject public ImplementationNodeFactory(GraphvizRenderer renderer, NameFactory nameFactory, PortIdFactory portIdFactory) { this.renderer = renderer; this.nameFactory = nameFactory; this.portIdFactory = portIdFactory; } public ImplementationNode newImplementationNode(String nodeId) { GraphvizNode node = new GraphvizNode(nodeId); renderer.addNode(node); return newAdaptor(node); } protected GraphvizNodeAdaptor newAdaptor(GraphvizNode node) { return new GraphvizNodeAdaptor(node); } /** * Adaptor class that converts {@link ImplementationNode} methods to display * operations on a {@link GraphvizNode}. */ protected class GraphvizNodeAdaptor implements ImplementationNode { protected final GraphvizNode node; public GraphvizNodeAdaptor(GraphvizNode node) { this.node = node; this.node.setStyle(NodeStyle.INVISIBLE); } public void setClassKey(Key key) { node.setHeaderBackgroundColor("#000000"); node.setHeaderTextColor("#ffffff"); node.setTitle(nameFactory.getClassName(key)); } public void setInstance(Object instance) { node.setHeaderBackgroundColor("#aaaaaa"); node.setHeaderTextColor("#ffffff"); node.setTitle(nameFactory.getInstanceName(instance)); } public void setSource(Object source) { node.addSubtitle(0, nameFactory.getSourceName(source)); } public void addMember(Member member) { node.addField(portIdFactory.getPortId(member), nameFactory.getMemberName(member)); } } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/NodeStyle.java0000644000175000017500000000223511214265012030317 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; /** * Styles for nodes. Similar to {@link EdgeStyle} but with a few more options. *

* See: http://www.graphviz.org/doc/info/attrs.html#k:style * * @author phopkins@gmail.com (Pete Hopkins) */ public enum NodeStyle { BOLD("bold"), DASHED("dashed"), DIAGONALS("diagonals"), DOTTED("dotted"), INVISIBLE("invis"), FILLED("filled"), ROUNDED("rounded"), SOLID("solid"); private final String name; NodeStyle(String name) { this.name = name; } @Override public String toString() { return name; } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/PortIdFactoryImpl.java0000644000175000017500000000171611214265012031767 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; import java.lang.reflect.Member; /** * Implementation of {@link PortIdFactory}. Bound in {@link GraphvizModule}. * * @author phopkins@gmail.com (Pete Hopkins) */ public class PortIdFactoryImpl implements PortIdFactory { public String getPortId(Member member) { return "m_" + Integer.toHexString(member.hashCode()); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/graphviz/EdgeStyle.java0000644000175000017500000000203711214265012030276 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher.graphviz; /** * Styles for edges. *

* See: http://www.graphviz.org/doc/info/attrs.html#k:style * * @author phopkins@gmail.com (Pete Hopkins) */ public enum EdgeStyle { BOLD("bold"), DASHED("dashed"), DOTTED("dotted"), INVISIBLE("invis"), SOLID("solid"); private final String name; EdgeStyle(String name) { this.name = name; } @Override public String toString() { return name; } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/ImplementationNode.java0000644000175000017500000000402711214265012030353 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.Key; import java.lang.reflect.Member; /** * Node for classes and instances that have {@link Dependency}s and are * bound to {@link InterfaceNode}s. These nodes will often have fields for * {@link Member}s that are {@link InjectionPoint}s. * * @see DependencyEdge * * @author phopkins@gmail.com (Pete Hopkins) * * @param The type for node IDs. */ public interface ImplementationNode { /** * Sets the {@link Key} that this node is for. Used when the node is * representing a class that Guice will instantiate. */ void setClassKey(Key key); /** * Sets the {@link Object} that's the already-created instance. Used when * this node is represeting the instance instead of a class. */ void setInstance(Object instance); void setSource(Object source); void addMember(Member member); /** * Factory interface for {@link ImplementationNode}s. Renderer * implementations will need to provide an implementation for this. * * @param The type for node IDs. * @param The {@link ImplementationNode} sub-type that this factory * provides. */ interface Factory> { /** * Creates a new {@link ImplementationNode} and adds it to the graph. * * @param nodeId ID for the node. * @return The new {@link ImplementationNode} instance. */ T newImplementationNode(K nodeId); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/NameFactory.java0000644000175000017500000000215111214265012026764 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.Key; import java.lang.reflect.Member; /** * Interface for a service that provides nice {@link String}s that we can * display in the graph for the types that come up in {@link Binding}s. * * @author phopkins@gmail.com (Pete Hopkins) */ public interface NameFactory { String getMemberName(Member member); String getClassName(Key key); String getInstanceName(Object instance); String getAnnotationName(Key key); String getSourceName(Object source); } guice-3.0/extensions/grapher/src/com/google/inject/grapher/Renderer.java0000644000175000017500000000221511214265012026323 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import java.io.IOException; /** * Interface for the service that renders the graph. It is assumed that the * implementations for {@link BindingEdge.Factory}, * {@link ImplementationNode.Factory}, etc. will have direct access to the * internals of the {@link Renderer} implementation, so the only external * interface needed is the {@link #render()} call that {@link InjectorGrapher} * calls when it's done. * * @author phopkins@gmail.com (Pete Hopkins) */ public interface Renderer { void render() throws IOException; } guice-3.0/extensions/grapher/src/com/google/inject/grapher/BindingEdge.java0000644000175000017500000000360711214265012026722 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; /** * Interface for an edge that connects an interface to the type or instance * that is bound to implement it. * * @author phopkins@gmail.com (Pete Hopkins) * * @param The type for node IDs. */ public interface BindingEdge { /** * Classification for what kind of binding this edge represents. */ enum Type { /** Binding is to an instance or class of the binding's same type. */ NORMAL, /** Binding is to an instance or class that provides the binding's type. */ PROVIDER, /** Binding is to the interface for a constant of a different type. */ CONVERTED_CONSTANT } void setType(Type type); /** * Factory interface for {@link BindingEdge}s. Renderer implementations will * need to provide an implementation for this. * * @param The type for node IDs. * @param The {@link BindingEdge} sub-type that this factory provides. */ interface Factory> { /** * Creates a new {@link BindingEdge} instance and adds it to the graph. * * @param fromId Node ID for the interface node. * @param toId Node ID for the implementation (class or instance) node. * @return The newly created and added {@link BindingEdge}. */ T newBindingEdge(K fromId, K toId); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/TransitiveDependencyVisitor.java0000644000175000017500000000630011413604602032266 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.Key; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Sets; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.ConstructorBinding; import com.google.inject.spi.ConvertedConstantBinding; import com.google.inject.spi.Dependency; import com.google.inject.spi.ExposedBinding; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InstanceBinding; import com.google.inject.spi.LinkedKeyBinding; import com.google.inject.spi.ProviderBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderKeyBinding; import com.google.inject.spi.UntargettedBinding; import java.util.Collection; import java.util.Set; /** * {@link BindingTargetVisitor} that returns a {@link Collection} of the * {@link Key}s of each {@link Binding}'s dependencies. Used by * {@link InjectorGropher} to walk the dependency graph from a starting set of * {@link Binding}s. * * @author phopkins@gmail.com (Pete Hopkins) */ public class TransitiveDependencyVisitor implements BindingTargetVisitor>> { private Collection> visitHasDependencies(HasDependencies hasDependencies) { Set> dependencies = Sets.newHashSet(); for (Dependency dependency : hasDependencies.getDependencies()) { dependencies.add(dependency.getKey()); } return dependencies; } public Collection> visit(ConstructorBinding binding) { return visitHasDependencies(binding); } public Collection> visit(ConvertedConstantBinding binding) { return visitHasDependencies(binding); } public Collection> visit(ExposedBinding binding) { // TODO(phopkins): Figure out if this is needed for graphing. return ImmutableSet.of(); } public Collection> visit(InstanceBinding binding) { return visitHasDependencies(binding); } public Collection> visit(LinkedKeyBinding binding) { return ImmutableSet.>of(binding.getLinkedKey()); } public Collection> visit(ProviderBinding binding) { return ImmutableSet.>of(binding.getProvidedKey()); } public Collection> visit(ProviderInstanceBinding binding) { return visitHasDependencies(binding); } public Collection> visit(ProviderKeyBinding binding) { return ImmutableSet.>of(binding.getProviderKey()); } public Collection> visit(UntargettedBinding binding) { // TODO(phopkins): Figure out if this is needed for graphing. return null; } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/NodeAliasFactory.java0000644000175000017500000000176411214265012027754 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; /** * Factory for aliasing one node ID to another. Used when we don't want to * render {@link Key}s from {@link Binding}s that are not interesting. * * @author phopkins@gmail.com (Pete Hopkins) */ public interface NodeAliasFactory { /** * Makes edges that would point to {@code fromId} point to * {@code toId} instead. */ void newAlias(K fromId, K toId); } guice-3.0/extensions/grapher/src/com/google/inject/grapher/GraphingVisitor.java0000644000175000017500000003370311461631440027710 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.Binding; import com.google.inject.Inject; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Nullable; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.ConstructorBinding; import com.google.inject.spi.ConvertedConstantBinding; import com.google.inject.spi.Dependency; import com.google.inject.spi.ExposedBinding; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.InstanceBinding; import com.google.inject.spi.LinkedKeyBinding; import com.google.inject.spi.ProviderBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderKeyBinding; import com.google.inject.spi.UntargettedBinding; import java.lang.reflect.Member; import java.util.Collection; import java.util.List; /** * {@link BindingTargetVisitor} that adds nodes and edges to the graph based on * the visited {@link Binding}. *

* This class is parameterized over the four graph element types * ({@link InterfaceNode}, {@link ImplementationNode}, {@link BindingEdge}, and * {@link DependencyEdge}) so that you can extend those interfaces and also * extend this class, and the helper methods will all return your new types. * * @author phopkins@gmail.com (Pete Hopkins) * * @param The type for node IDs. * @param Type for {@link InterfaceNode}s. * @param Type for {@link ImplementationNode}.s * @param Type for {@link BindingEdge}s. * @param Type for {@link DependencyEdge}s. */ public class GraphingVisitor, M extends ImplementationNode, B extends BindingEdge, D extends DependencyEdge> implements BindingTargetVisitor { private final NodeIdFactory idFactory; private final InterfaceNode.Factory interfaceNodeFactory; private final ImplementationNode.Factory implementationNodeFactory; private final BindingEdge.Factory bindingEdgeFactory; private final DependencyEdge.Factory dependencyEdgeFactory; private final NodeAliasFactory nodeAliasFactory; @Inject public GraphingVisitor(NodeIdFactory idFactory, InterfaceNode.Factory interfaceNodeFactory, ImplementationNode.Factory implementationNodeFactory, BindingEdge.Factory bindingEdgeFactory, DependencyEdge.Factory dependencyEdgeFactory, NodeAliasFactory nodeAliasFactory) { this.idFactory = idFactory; this.interfaceNodeFactory = interfaceNodeFactory; this.implementationNodeFactory = implementationNodeFactory; this.bindingEdgeFactory = bindingEdgeFactory; this.dependencyEdgeFactory = dependencyEdgeFactory; this.nodeAliasFactory = nodeAliasFactory; } /** * Helper method to return the standard node ID for the {@link Binding}'s * {@link Key}. * * @see NodeIdFactory#getClassNodeId(Key) */ protected final K getClassNodeId(Binding binding) { return idFactory.getClassNodeId(binding.getKey()); } /** * Helper method to return the instance node ID for the {@link Binding}'s * {@link Key}. * * @see NodeIdFactory#getInstanceNodeId(Key) */ protected final K getInstanceNodeId(Binding binding) { return idFactory.getInstanceNodeId(binding.getKey()); } /** * Creates and returns a new {@link InterfaceNode} object for the given * {@link Binding}. */ protected N newInterfaceNode(Binding binding) { N node = interfaceNodeFactory.newInterfaceNode(getClassNodeId(binding)); node.setKey(binding.getKey()); node.setSource(binding.getSource()); return node; } /** * Creates and returns a new {@link ImplementationNode} for the given * {@link Binding}, where the {@link Binding} is for a class that Guice * will instantiate, rather than a specific instance. */ protected M newClassImplementationNode(Binding binding, InjectionPoint constructorInjectionPoint, Collection memberInjectionPoints) { M node = implementationNodeFactory.newImplementationNode(getClassNodeId(binding)); node.setClassKey(binding.getKey()); // we don't set the source here because it's not interesting for classes node.addMember(constructorInjectionPoint.getMember()); for (InjectionPoint injectionPoint : memberInjectionPoints) { node.addMember(injectionPoint.getMember()); } return node; } /** * Creates and returns a new {@link ImplementationNode} for the given * {@link Binding}, where the {@link Binding} is for an instance, rather than * a class. */ protected M newInstanceImplementationNode(Binding binding, Object instance) { M node = implementationNodeFactory.newImplementationNode(getInstanceNodeId(binding)); node.setSource(binding.getSource()); node.setInstance(instance); return node; } /** * Creates a new {@link BindingEdge} from the given node to the specified * node. * * @param nodeId ID of the {@link InterfaceNode} that binds to the other. * @param toId The node ID of a class or instance that is bound. * @param type The {@link BindingEdge.Type} of this binding. * @return The newly-created and added {@link BindingEdge}. */ protected B newBindingEdge(K nodeId, K toId, BindingEdge.Type type) { B edge = bindingEdgeFactory.newBindingEdge(nodeId, toId); edge.setType(type); return edge; } /** * Adds {@link DependencyEdge}s to the graph for each of the provided * {@link Dependency}s. These will be from the given node ID to the * {@link Dependency}'s {@link Key}. *

* If a {@link Dependency} has an associated {@link InjectionPoint}, its * member will be added to the given {@link ImplementationNode} and the edge * will start at the {@link Member}. * * @see #newDependencyEdge(Object, InjectionPoint, Dependency) * * @param nodeId ID of the node that should be the tail of the * {@link DependencyEdge}s. * @param node An {@link ImplementationNode} to add {@link Member}s to. * @param dependencies {@link Collection} of {@link Dependency}s from the * {@link Binding}. * @return A {@link Collection} of the {@link DependencyEdge}s that were * added to the graph. */ protected Collection newDependencyEdges(K nodeId, M node, Collection> dependencies) { List edges = Lists.newArrayList(); for (Dependency dependency : dependencies) { InjectionPoint injectionPoint = dependency.getInjectionPoint(); if (injectionPoint != null) { node.addMember(injectionPoint.getMember()); } D edge = newDependencyEdge(nodeId, injectionPoint, dependency); edges.add(edge); } return edges; } /** * Creates a new {@link DependencyEdge} from the given node to a * {@link Dependency}. *

* This method takes more comprehensive parameters than strictly necessary * in case they would be useful to overriding implementations. * * @param nodeId ID of the {@link ImplementationNode} where the edges will start. * @param injectionPoint The {@link InjectionPoint} that gave rise to this * {@link Dependency}, if one exists. Used to figure out which * {@link Member} the edge should point from. * @param dependency The {@link Dependency} to represent with this edge. * @return The newly-created and added {@link DependencyEdge}. */ protected D newDependencyEdge(K nodeId, @Nullable InjectionPoint injectionPoint, Dependency dependency) { K toId = idFactory.getClassNodeId(dependency.getKey()); return dependencyEdgeFactory.newDependencyEdge(nodeId, injectionPoint, toId); } /** * Visitor for {@link ConstructorBinding}s. These are for classes that Guice * will instantiate to satisfy injection requests. We create a new * {@link ImplementationNode} for the class, then add edges to everything * that it depends on to be instantiated. * * @see #newClassImplementationNode(Binding, InjectionPoint, Collection) * @see #newDependencyEdges(Object, ImplementationNode, Collection) */ public Void visit(ConstructorBinding binding) { M node = newClassImplementationNode(binding, binding.getConstructor(), binding.getInjectableMembers()); newDependencyEdges(getClassNodeId(binding), node, binding.getDependencies()); return null; } /** * Visitor for {@link ConvertedConstantBinding}. The {@link Binding}'s * {@link Key} will be of an annotated primitive type, and the value of * {@link ConvertedConstantBinding#getSourceKey()} will be of a * {@link String} with the same annotation. *

* We render this as an {@link InterfaceNode} that has a * {@link BindingEdge} to the source {@link Key}. That will then be rendered * by {@link #visit(InstanceBinding)} as an {@link InterfaceNode} * with a {@link BindingEdge} to the {@link String} instance. * * @see #newInterfaceNode(Binding) * @see #newBindingEdge(Object, Object, com.google.inject.grapher.BindingEdge.Type) */ public Void visit(ConvertedConstantBinding binding) { newInterfaceNode(binding); newBindingEdge(getClassNodeId(binding), idFactory.getClassNodeId(binding.getSourceKey()), BindingEdge.Type.CONVERTED_CONSTANT); return null; } /** * Currently not displayed on the graph. */ public Void visit(ExposedBinding binding) { // TODO(phopkins): Decide if this is needed for graphing. return null; } /** * Visitor for {@link InstanceBinding}. We render two nodes in this case: a * {@link InterfaceNode} for the binding's {@link Key}, and then an * {@link ImplementationNode} for the instance {@link Object} itself. We run * a binding node between them. *

* We then render any {@link DependencyEdge}s that the instance may have, * which come either from {@link InjectionPoint}s (method and field) on the * instance, or on {@link Dependency}s the instance declares through the * {@link HasDependencies} interface. * * @see #newInterfaceNode(Binding) * @see #newBindingEdge(Object, Object, com.google.inject.grapher.BindingEdge.Type) * @see #newInstanceImplementationNode(Binding, Object) * @see #newDependencyEdges(Object, ImplementationNode, java.util.Collection) */ public Void visit(InstanceBinding binding) { newInterfaceNode(binding); newBindingEdge(getClassNodeId(binding), getInstanceNodeId(binding), BindingEdge.Type.NORMAL); M node = newInstanceImplementationNode(binding, binding.getInstance()); newDependencyEdges(getInstanceNodeId(binding), node, binding.getDependencies()); return null; } /** * Visitor for {@link LinkedKeyBinding}. This is the standard {@link Binding} * you get from binding an interface class to an implementation class. We * create an {@link InterfaceNode}, then draw a {@link BindingEdge} to the * node of the implementing class. * * @see #newInterfaceNode(Binding) * @see #newBindingEdge(Object, Object, com.google.inject.grapher.BindingEdge.Type) */ public Void visit(LinkedKeyBinding binding) { newInterfaceNode(binding); newBindingEdge(getClassNodeId(binding), idFactory.getClassNodeId(binding.getLinkedKey()), BindingEdge.Type.NORMAL); return null; } /** * Visitor for {@link ProviderBinding}. These {@link Binding}s arise from an * {@link InjectionPoint} for the {@link Provider} interface. Since this * isn't tremendously interesting information, we don't render this binding * on the graph, and instead let the {@link DependencyEdge} go straight from * the {@link InjectionPoint} to the node specified by * {@link ProviderBinding#getProvidedKey()}. * * @see NodeAliasFactory#newAlias(Object, Object) */ public Void visit(ProviderBinding binding) { nodeAliasFactory.newAlias(getClassNodeId(binding), idFactory.getClassNodeId(binding.getProvidedKey())); return null; } /** * Same as {@link #visit(InstanceBinding)}, but the * {@link BindingEdge} is {@link BindingEdge.Type#PROVIDER}. * * @see #newInterfaceNode(Binding) * @see #newBindingEdge(Object, Object, com.google.inject.grapher.BindingEdge.Type) * @see #newInstanceImplementationNode(Binding, Object) * @see #newDependencyEdges(Object, ImplementationNode, java.util.Collection) */ public Void visit(ProviderInstanceBinding binding) { newInterfaceNode(binding); newBindingEdge(getClassNodeId(binding), getInstanceNodeId(binding), BindingEdge.Type.PROVIDER); M node = newInstanceImplementationNode(binding, binding.getProviderInstance()); newDependencyEdges(getInstanceNodeId(binding), node, binding.getDependencies()); return null; } /** * Same as {@link #visit(LinkedKeyBinding)}, but the * {@link BindingEdge} is {@link BindingEdge.Type#PROVIDER}. * * @see #newInterfaceNode(Binding) * @see #newBindingEdge(Object, Object, com.google.inject.grapher.BindingEdge.Type) */ public Void visit(ProviderKeyBinding binding) { newInterfaceNode(binding); newBindingEdge(getClassNodeId(binding), idFactory.getClassNodeId(binding.getProviderKey()), BindingEdge.Type.PROVIDER); return null; } /** * Currently not displayed on the graph. */ public Void visit(UntargettedBinding binding) { // TODO(phopkins): Decide if this is needed for graphing. return null; } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/GrapherModule.java0000644000175000017500000000336411214265012027321 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.AbstractModule; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.spi.BindingTargetVisitor; import java.util.Collection; /** * Module for the common bindings for {@link InjectorGrapher}. You will also * need to bind a {@link Module} that satisfies the {@link Renderer} * dependency. *

* If you want to use subtypes of the node and edge classes, or a different * node ID type, you will need to override the {@link GraphingVisitor} binding * to specify the new type parameters. * * @author phopkins@gmail.com (Pete Hopkins) */ public class GrapherModule extends AbstractModule { @Override protected void configure() { requireBinding(Renderer.class); bind(InjectorGrapher.class); bind(new TypeLiteral>>>() {}) .to(TransitiveDependencyVisitor.class); bind(new TypeLiteral>() {}) .to(new TypeLiteral, ImplementationNode, BindingEdge, DependencyEdge>>() {}); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/InterfaceNode.java0000644000175000017500000000304111214265012027261 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.Key; /** * Node for an interface class that has been bound to an implementation class * or instance. These nodes are basically defined by a {@link Key}. * * @see BindingEdge * * @author phopkins@gmail.com (Pete Hopkins) * * @param The type for node IDs. */ public interface InterfaceNode { void setKey(Key key); void setSource(Object source); /** * Factory interface for {@link InterfaceNode}s. Renderer implementations * will need to provide an implementation for this. * * @param The type for node IDs. * @param The {@link InterfaceNode} sub-type that this factory provides. */ interface Factory> { /** * Creates a new {@link InterfaceNode} and adds it to the graph. * * @param nodeId ID for the node. * @return The new {@link InterfaceNode} instance. */ T newInterfaceNode(K nodeId); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/NodeIdFactory.java0000644000175000017500000000234311214265012027251 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.Key; /** * Factory for abstract identifiers for elements on the graph. Most graph nodes * will correspond directly to {@link Key}s, but we do this for additional * flexibility and because instances do not have separate {@link Key}s from the * interfaces they are bound to. *

* Node IDs are treated as opaque values by {@link GraphingVisitor} and the * other classes in this package. * * @author phopkins@gmail.com (Pete Hopkins) * * @param The type for node IDs. */ public interface NodeIdFactory { K getClassNodeId(Key key); K getInstanceNodeId(Key key); } guice-3.0/extensions/grapher/src/com/google/inject/grapher/ShortNameFactory.java0000644000175000017500000001042711413604602030014 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Join; import com.google.inject.internal.util.Lists; import com.google.inject.internal.ProviderMethod; import com.google.inject.internal.util.StackTraceElements; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.List; /** * Reasonable implementation for {@link NameFactory}. Mostly takes various * {@link Object#toString()}s and strips package names out of them so that * they'll fit on the graph. * * @author phopkins@gmail.com (Pete Hopkins) */ public class ShortNameFactory implements NameFactory { public String getMemberName(Member member) { if (member instanceof Constructor) { return ""; } else if (member instanceof Method) { return "#" + member.getName() + "(...)"; } else { return member.getName(); } } public String getAnnotationName(Key key) { Annotation annotation = key.getAnnotation(); Class annotationType = key.getAnnotationType(); if (annotation != null) { annotationType = annotation.annotationType(); String annotationString = annotation.toString(); String canonicalName = annotationType.getName(); String simpleName = annotationType.getSimpleName(); return annotationString.replace(canonicalName, simpleName).replace("()", ""); } else if (annotationType != null) { return "@" + annotationType.getSimpleName(); } else { return ""; } } public String getClassName(Key key) { TypeLiteral typeLiteral = key.getTypeLiteral(); return stripPackages(typeLiteral.toString()); } public String getInstanceName(Object instance) { if (instance instanceof ProviderMethod) { return getMethodString(((ProviderMethod) instance).getMethod()); } if (instance instanceof CharSequence) { return "\"" + instance + "\""; } try { if (instance.getClass().getMethod("toString").getDeclaringClass().equals(Object.class)) { return stripPackages(instance.getClass().getName()); } } catch (SecurityException e) { throw new AssertionError(e); } catch (NoSuchMethodException e) { throw new AssertionError(e); } return instance.toString(); } /** * Returns a name for a Guice "source" object. This will typically be either * a {@link StackTraceElement} for when the binding is made to the instance, * or a {@link Method} when a provider method is used. */ public String getSourceName(Object source) { if (source instanceof Method) { source = StackTraceElements.forMember((Method) source); } if (source instanceof StackTraceElement) { return getFileString((StackTraceElement) source); } return stripPackages(source.toString()); } protected String getFileString(StackTraceElement stackTraceElement) { return stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber(); } protected String getMethodString(Method method) { List paramStrings = Lists.newArrayList(); for (Class paramType : method.getParameterTypes()) { paramStrings.add(paramType.getSimpleName()); } String paramString = Join.join(", ", paramStrings); return "#" + method.getName() + "(" + paramString + ")"; } /** * Eliminates runs of lowercase characters and numbers separated by periods. * Seems to remove packages from fully-qualified type names pretty well. */ private String stripPackages(String str) { return str.replaceAll("(^|[< .\\(])([a-z0-9]+\\.)*", "$1"); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/StringNodeIdFactory.java0000644000175000017500000000215611214265012030442 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.Key; /** * {@link IdFactory} implementation that for {@link String} node IDs. The IDs * are comprised of letters, numbers and underscores. * * @author phopkins@gmail.com (Pete Hopkins) */ public class StringNodeIdFactory implements NodeIdFactory { public String getClassNodeId(Key key) { return "k_" + Integer.toHexString(key.hashCode()); } public String getInstanceNodeId(Key key) { return "i_" + Integer.toHexString(key.hashCode()); } } guice-3.0/extensions/grapher/src/com/google/inject/grapher/InjectorGrapher.java0000644000175000017500000001210211526702200027640 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.grapher; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.internal.util.Sets; import com.google.inject.spi.BindingTargetVisitor; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.Set; import java.util.logging.Logger; /** * Root class for graphing an {@link Injector}. Bound in {@link GrapherModule}. *

* Use {@link #of(Injector)} to specify the {@link Injector} to use, and * {@link graph()} to graph the {@link Injector} using the currently-bound * {@link Renderer}. *

* By default, this will graph the entire {@link Injector}. Use * {@link #rootedAt(Class...)} or {@link #rootedAt(Key...)} to specify an * initial set of {@link Class}es or {@link Key}s to use, and this will graph * their transitive bindings and dependencies. * * @author phopkins@gmail.com (Pete Hopkins) */ public class InjectorGrapher { private static final Key loggerKey = Key.get(Logger.class); private final BindingTargetVisitor>> keyVisitor; private final BindingTargetVisitor graphingVisitor; private final Renderer renderer; private Injector injector; private Set> root; @Inject public InjectorGrapher(BindingTargetVisitor>> keyVisitor, BindingTargetVisitor graphingVisitor, Renderer renderer) { this.keyVisitor = keyVisitor; this.graphingVisitor = graphingVisitor; this.renderer = renderer; } /** * Sets the {@link Injector} to graph. */ public InjectorGrapher of(Injector injector) { this.injector = injector; return this; } /** * Sets an initial group of {@link Class}es to use as the starting point for * the graph. The graph will be of these classes and their transitive * dependencies and bindings. */ public InjectorGrapher rootedAt(Class... classes) { this.root = Sets.newHashSet(); for (Class clazz : classes) { this.root.add(Key.get(clazz)); } return this; } /** * Sets an initial group of {@link Key}s to use as the starting point for * the graph. The graph will be of these keys and their transitive * dependencies and bindings. */ public InjectorGrapher rootedAt(Key... keys) { this.root = Sets.newHashSet(); for (Key key : keys) { this.root.add(key); } return this; } /** * Renders a graph with the bound {@link Renderer}. The {@link Injector} * must have already been specified with {@link #of(Injector)}. */ public void graph() throws IOException { processBindings(); renderer.render(); } /** * Tests for {@link Key}s that we don't want to include by default in the * graph. They're left out of the initial set, but will appear if depended * upon by other classes. Leaves out Guice classes (such as the * {@link Injector}) and the {@link Logger}. */ private boolean skipKey(Key key) { return key.getTypeLiteral().getRawType().getPackage() == Guice.class.getPackage() || loggerKey.equals(key); } /** * Takes the set of starting {@link Binding}s, which comes either from the * {@link Injector} or from {@link #rootedAt(Class...)}, and applies the * {@link #graphingVisitor} to them. Uses the {@link #keyVisitor} to build * out the set of {@link Key}s so that the graph covers the transitive * dependencies and bindings. */ private void processBindings() { Set> keys = Sets.newLinkedHashSet(); Set> visitedKeys = Sets.newHashSet(); // build up the root set from the Injector if it wasn't specified if (root == null) { for (Key key : injector.getBindings().keySet()) { if (!skipKey(key)) { keys.add(key); } } } else { keys.addAll(root); } while (!keys.isEmpty()) { Iterator> iterator = keys.iterator(); Key key = iterator.next(); iterator.remove(); if (visitedKeys.contains(key)) { continue; } Binding binding = injector.getBinding(key); visitedKeys.add(key); binding.acceptTargetVisitor(graphingVisitor); // find the dependencies and make sure that they get visited Collection> newKeys = binding.acceptTargetVisitor(keyVisitor); if (newKeys != null) { keys.addAll(newKeys); } } } } guice-3.0/extensions/persist/0000755000175000017500000000000011542727756016254 5ustar drazzibdrazzibguice-3.0/extensions/persist/build/0000755000175000017500000000000011542727756017353 5ustar drazzibdrazzibguice-3.0/extensions/persist/build/META-INF/0000755000175000017500000000000011542727756020513 5ustar drazzibdrazzibguice-3.0/extensions/persist/build/META-INF/MANIFEST.MF0000644000175000017500000000147511542727754022152 0ustar drazzibdrazzibManifest-Version: 1.0 Export-Package: com.google.inject.persist.finder;version="1.3",com.goo gle.inject.persist.jpa;version="1.3",com.google.inject.persist;versio n="1.3" Bundle-Name: guice-persist Created-By: 1.6.0_23 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-Copyright: Copyright (C) 2006 Google Inc. Bundle-Vendor: Google, Inc. Fragment-Host: com.google.inject Bundle-Version: 3.0 Bundle-ManifestVersion: 2 Bundle-Description: Guice is a lightweight dependency injection framew ork for Java 5 and above Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-DocURL: http://code.google.com/p/google-guice/ Bundle-SymbolicName: com.google.inject.persist Import-Package: javax.inject,javax.persistence,javax.servlet,org.aopal liance.intercept guice-3.0/extensions/persist/build/dist/0000755000175000017500000000000011542727756020316 5ustar drazzibdrazzibguice-3.0/extensions/persist/build/classes/0000755000175000017500000000000011542727756021010 5ustar drazzibdrazzibguice-3.0/extensions/persist/build/classes/log4j.properties0000644000175000017500000000040711542727756024146 0ustar drazzibdrazziblog4j.rootLogger=warn, console log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.Target=System.out log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%p [%c{1}] - %m %n guice-3.0/extensions/persist/build/classes/com/0000755000175000017500000000000011542727756021566 5ustar drazzibdrazzibguice-3.0/extensions/persist/build/classes/com/google/0000755000175000017500000000000011542727756023042 5ustar drazzibdrazzibguice-3.0/extensions/persist/build/classes/com/google/inject/0000755000175000017500000000000011542727756024316 5ustar drazzibdrazzibguice-3.0/extensions/persist/build/classes/com/google/inject/persist/0000755000175000017500000000000011542727756026007 5ustar drazzibdrazzibguice-3.0/extensions/persist/build/classes/com/google/inject/persist/finder/0000755000175000017500000000000011542727756027256 5ustar drazzibdrazzibguice-3.0/extensions/persist/build/classes/com/google/inject/persist/jpa/0000755000175000017500000000000011542727756026561 5ustar drazzibdrazzibguice-3.0/extensions/persist/pom.xml0000644000175000017500000000323411464733666017573 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-persist Google Guice - Extensions - Persist javax.persistence persistence-api 1.0 provided javax.servlet servlet-api 2.5 provided org.slf4j slf4j-simple 1.6.1 test org.hibernate hibernate-entitymanager 3.4.0.GA test org.hsqldb hsqldb-j5 2.0.0 test maven-surefire-plugin never guice-3.0/extensions/persist/build.xml0000644000175000017500000000132611461503360020056 0ustar drazzibdrazzib guice-3.0/extensions/persist/lib/0000755000175000017500000000000011442650754017012 5ustar drazzibdrazzibguice-3.0/extensions/persist/persist.iml0000644000175000017500000000217011442650756020442 0ustar drazzibdrazzib guice-3.0/extensions/persist/build.properties0000644000175000017500000000025111461372032021446 0ustar drazzibdrazziblib.dir=../../lib ext.lib.dir=lib src.dir=src test.dir=test build.dir=build test.class=com.google.inject.persist.AllTests module=com.google.inject.persist fragment=true guice-3.0/extensions/persist/test/0000755000175000017500000000000011407727612017222 5ustar drazzibdrazzibguice-3.0/extensions/persist/test/META-INF/0000755000175000017500000000000011407727612020362 5ustar drazzibdrazzibguice-3.0/extensions/persist/test/META-INF/persistence.xml0000644000175000017500000000266411407727612023440 0ustar drazzibdrazzib org.hibernate.ejb.HibernatePersistence com.google.inject.persist.jpa.JpaTestEntity com.google.inject.persist.jpa.JpaParentTestEntity true guice-3.0/extensions/persist/test/com/0000755000175000017500000000000011407727612020000 5ustar drazzibdrazzibguice-3.0/extensions/persist/test/com/google/0000755000175000017500000000000011407727612021254 5ustar drazzibdrazzibguice-3.0/extensions/persist/test/com/google/inject/0000755000175000017500000000000011407727612022530 5ustar drazzibdrazzibguice-3.0/extensions/persist/test/com/google/inject/persist/0000755000175000017500000000000011443132316024210 5ustar drazzibdrazzibguice-3.0/extensions/persist/test/com/google/inject/persist/EdslTest.java0000644000175000017500000000115711501200536026601 0ustar drazzibdrazzibpackage com.google.inject.persist; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Stage; import com.google.inject.persist.jpa.JpaPersistModule; import junit.framework.TestCase; /** * @author dhanji@google.com (Dhanji R. Prasanna) */ public class EdslTest extends TestCase { public void testModuleConfigUsingJpa() throws Exception { Guice.createInjector(Stage.PRODUCTION, new AbstractModule() { @Override protected void configure() { install(new JpaPersistModule("myunit")); binder().requireExplicitBindings(); }; }); } } guice-3.0/extensions/persist/test/com/google/inject/persist/jpa/0000755000175000017500000000000011443132316024762 5ustar drazzibdrazzibguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsTest.java0000644000175000017500000000710711443132316033253 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; import java.util.Date; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import junit.framework.TestCase; /** * For instance, a session-per-request strategy will control the opening and closing of the EM at * its own (manual) discretion. As opposed to a transactional unit of work. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class ManualLocalTransactionsTest extends TestCase { private Injector injector; private static final String UNIQUE_TEXT = "some unique text" + new Date(); private static final String UNIQUE_TEXT_2 = "some other unique text" + new Date(); public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); //startup persistence injector.getInstance(PersistService.class).start(); } public void tearDown() { injector.getInstance(EntityManagerFactory.class).close(); } public void testSimpleCrossTxnWork() { injector.getInstance(UnitOfWork.class).begin(); //pretend that the request was started here EntityManager em = injector.getInstance(EntityManager.class); JpaTestEntity entity = injector.getInstance(TransactionalObject.class).runOperationInTxn(); injector.getInstance(TransactionalObject.class).runOperationInTxn2(); //persisted entity should remain in the same em (which should still be open) assertTrue("EntityManager appears to have been closed across txns!", injector.getInstance(EntityManager.class).contains(entity)); assertTrue("EntityManager appears to have been closed across txns!", em.contains(entity)); assertTrue("EntityManager appears to have been closed across txns!", em.isOpen()); injector.getInstance(UnitOfWork.class).end(); injector.getInstance(UnitOfWork.class).begin(); //try to query them back out em = injector.getInstance(EntityManager.class); assertNotNull(em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT).getSingleResult()); assertNotNull(em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT_2).getSingleResult()); em.close(); assertFalse(em.isOpen()); } public static class TransactionalObject { @Inject EntityManager em; @Transactional public JpaTestEntity runOperationInTxn() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT); em.persist(entity); return entity; } @Transactional public void runOperationInTxn2() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT_2); em.persist(entity); } } }././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsConfidenceTest.javaguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsConfidenceTes0000644000175000017500000000573711443132316034134 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import java.util.Date; import javax.persistence.EntityManager; import javax.persistence.PersistenceException; import junit.framework.TestCase; /** * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class ManualLocalTransactionsConfidenceTest extends TestCase { private Injector injector; private static final String UNIQUE_TEXT_3 = ManualLocalTransactionsConfidenceTest.class.getSimpleName() + "CONSTRAINT_VIOLATING some other unique text" + new Date(); @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); //startup persistence injector.getInstance(PersistService.class).start(); } @Override public final void tearDown() { injector.getInstance(PersistService.class).stop(); } public void testThrowingCleanupInterceptorConfidence() { Exception e = null; try { System.out.println( "\n\n******************************* EXPECTED EXCEPTION NORMAL TEST BEHAVIOR **********"); injector.getInstance(TransactionalObject.class).runOperationInTxn(); fail(); } catch (RuntimeException re) { e = re; System.out.println( "\n\n******************************* EXPECTED EXCEPTION NORMAL TEST BEHAVIOR **********"); re.printStackTrace(System.out); System.out.println( "\n\n**********************************************************************************"); } assertNotNull("No exception was thrown!", e); assertTrue("Exception thrown was not what was expected (i.e. commit-time)", e instanceof PersistenceException); } public static class TransactionalObject { @Inject EntityManager em; @Transactional public void runOperationInTxn() { JpaParentTestEntity entity = new JpaParentTestEntity(); JpaTestEntity child = new JpaTestEntity(); child.setText(UNIQUE_TEXT_3); em.persist(child); entity.getChildren().add(child); em.persist(entity); entity = new JpaParentTestEntity(); entity.getChildren().add(child); em.persist(entity); } } } guice-3.0/extensions/persist/test/com/google/inject/persist/jpa/JpaWorkManagerTest.java0000644000175000017500000000703011443132316031335 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; import java.util.Date; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Query; import junit.framework.TestCase; /** * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class JpaWorkManagerTest extends TestCase { private Injector injector; private static final String UNIQUE_TEXT_3 = JpaWorkManagerTest.class.getSimpleName() + "CONSTRAINT_VIOLATING some other unique text" + new Date(); @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); //startup persistence injector.getInstance(PersistService.class).start(); } @Override public void tearDown() { injector.getInstance(EntityManagerFactory.class).close(); } public void testWorkManagerInSession() { injector.getInstance(UnitOfWork.class).begin(); try { injector.getInstance(TransactionalObject.class).runOperationInTxn(); } finally { injector.getInstance(UnitOfWork.class).end(); } injector.getInstance(UnitOfWork.class).begin(); injector.getInstance(EntityManager.class).getTransaction().begin(); try { final Query query = injector.getInstance(EntityManager.class) .createQuery("select e from JpaTestEntity as e where text = :text"); query.setParameter("text", UNIQUE_TEXT_3); final Object o = query.getSingleResult(); assertNotNull("no result!!", o); assertTrue("Unknown type returned " + o.getClass(), o instanceof JpaTestEntity); JpaTestEntity ent = (JpaTestEntity) o; assertEquals("Incorrect result returned or not persisted properly" + ent.getText(), UNIQUE_TEXT_3, ent.getText()); } finally { injector.getInstance(EntityManager.class).getTransaction().commit(); injector.getInstance(UnitOfWork.class).end(); } } public void testCloseMoreThanOnce() { injector.getInstance(PersistService.class).stop(); try { injector.getInstance(PersistService.class).stop(); fail(); } catch (IllegalStateException e) { // Ignored. } } public static class TransactionalObject { @Inject EntityManager em; @Transactional public void runOperationInTxn() { JpaTestEntity testEntity = new JpaTestEntity(); testEntity.setText(UNIQUE_TEXT_3); em.persist(testEntity); } @Transactional public void runOperationInTxnError() { JpaTestEntity testEntity = new JpaTestEntity(); testEntity.setText(UNIQUE_TEXT_3 + "transient never in db!" + hashCode()); em.persist(testEntity); } } }././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/CustomPropsEntityManagerFactoryProvisionTest.javaguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/CustomPropsEntityManagerFactoryProvi0000644000175000017500000000360711443132316034251 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.UnitOfWork; import java.util.Properties; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import junit.framework.TestCase; /** * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class CustomPropsEntityManagerFactoryProvisionTest extends TestCase { private Injector injector; @Override public void setUp() { Properties props = new Properties(); props.put("blah", "blah"); injector = Guice.createInjector(new JpaPersistModule("testUnit").properties(props)); } @Override public final void tearDown() { injector.getInstance(UnitOfWork.class).end(); injector.getInstance(EntityManagerFactory.class).close(); } public void testSessionCreateOnInjection() { assertEquals("SINGLETON VIOLATION " + UnitOfWork.class.getName(), injector.getInstance(UnitOfWork.class), injector.getInstance(UnitOfWork.class)); //startup persistence injector.getInstance(PersistService.class).start(); //obtain em assertTrue(injector.getInstance(EntityManager.class).isOpen()); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsWithCustomMatcherTest.javaguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/ManualLocalTransactionsWithCustomMat0000644000175000017500000000707011443132316034163 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; import java.util.Date; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import junit.framework.TestCase; /** * Created with IntelliJ IDEA. On: 2/06/2007 * * For instance, a session-per-request strategy will control the opening and closing of the EM at * its own (manual) discretion. As opposed to a transactional unit of work. * * @author Dhanji R. Prasanna (dhanji@gmail.com) * @since 1.0 */ public class ManualLocalTransactionsWithCustomMatcherTest extends TestCase { private Injector injector; private static final String UNIQUE_TEXT = "some unique text" + new Date(); private static final String UNIQUE_TEXT_2 = "some other unique text" + new Date(); @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); //startup persistence injector.getInstance(PersistService.class).start(); } @Override public void tearDown() { injector.getInstance(EntityManagerFactory.class).close(); } public void testSimpleCrossTxnWork() { //pretend that the request was started here EntityManager em = injector.getInstance(EntityManager.class); JpaTestEntity entity = injector .getInstance(ManualLocalTransactionsWithCustomMatcherTest.TransactionalObject.class) .runOperationInTxn(); injector.getInstance(ManualLocalTransactionsWithCustomMatcherTest.TransactionalObject.class) .runOperationInTxn2(); //persisted entity should remain in the same em (which should still be open) assertTrue("EntityManager appears to have been closed across txns!", injector.getInstance(EntityManager.class).contains(entity)); assertTrue("EntityManager appears to have been closed across txns!", em.contains(entity)); assertTrue("EntityManager appears to have been closed across txns!", em.isOpen()); injector.getInstance(UnitOfWork.class).end(); //try to query them back out em = injector.getInstance(EntityManager.class); assertNotNull(em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT).getSingleResult()); assertNotNull(em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT_2).getSingleResult()); em.close(); } public static class TransactionalObject { @Inject EntityManager em; @Transactional public JpaTestEntity runOperationInTxn() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT); em.persist(entity); return entity; } @Transactional public void runOperationInTxn2() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT_2); em.persist(entity); } } } guice-3.0/extensions/persist/test/com/google/inject/persist/jpa/DynamicFinderTest.java0000644000175000017500000000616511443132316031211 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Provider; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.finder.Finder; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.UUID; import javax.persistence.EntityManager; import junit.framework.TestCase; /** * A test around providing sessions (starting, closing etc.) * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class DynamicFinderTest extends TestCase { private Injector injector; public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit").addFinder(JpaFinder.class)); //startup persistence injector.getInstance(PersistService.class).start(); } public final void tearDown() { injector.getInstance(PersistService.class).stop(); } public void testDynamicFinderListAll() { //obtain em JpaDao dao = injector.getInstance(JpaDao.class); //obtain same em again (bound to txn) JpaTestEntity te = new JpaTestEntity(); te.setText("HIAjsOKAOSD" + new Date() + UUID.randomUUID().toString()); dao.persist(te); //im not sure this hack works... assertFalse("Duplicate entity managers crossing-scope", dao.lastEm.equals(injector.getInstance(EntityManager.class))); List list = injector.getInstance(JpaFinder.class).listAll(); assertNotNull(list); assertFalse(list.isEmpty()); assertEquals(1, list.size()); assertEquals(te, list.get(0)); } public static interface JpaFinder { @Finder(query = "from JpaTestEntity", returnAs = ArrayList.class) public List listAll(); } public static class JpaDao { private final Provider em; EntityManager lastEm; @Inject public JpaDao(Provider em) { this.em = em; } @Transactional public void persist(T t) { lastEm = em.get(); assertTrue("em is not open!", lastEm.isOpen()); assertTrue("no active txn!", lastEm.getTransaction().isActive()); lastEm.persist(t); assertTrue("Persisting object failed", lastEm.contains(t)); } @Transactional public boolean contains(T t) { if (null == lastEm) { lastEm = em.get(); } return lastEm.contains(t); } } }././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsAcrossRequestTest.javaguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsAcrossReques0000644000175000017500000002015511443132316034150 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.name.Named; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; import com.google.inject.persist.finder.Finder; import java.io.IOException; import java.util.Date; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.NoResultException; import junit.framework.TestCase; /** * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class ManagedLocalTransactionsAcrossRequestTest extends TestCase { private Injector injector; private static final String UNIQUE_TEXT = "some unique text" + new Date(); private static final String UNIQUE_TEXT_MERGE = "meRG_Esome unique text" + new Date(); private static final String UNIQUE_TEXT_MERGE_FORDF = "aSdoaksdoaksdmeRG_Esome unique text" + new Date(); private static final String TRANSIENT_UNIQUE_TEXT = "some other unique text" + new Date(); @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); //startup persistence injector.getInstance(PersistService.class).start(); } @Override public final void tearDown() { injector.getInstance(EntityManagerFactory.class).close(); } public void testSimpleTransaction() { injector.getInstance(TransactionalObject.class).runOperationInTxn(); EntityManager em = injector.getInstance(EntityManager.class); assertFalse(em.getTransaction().isActive()); //test that the data has been stored Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); assertTrue("odd result returned fatal", result instanceof JpaTestEntity); assertEquals("queried entity did not match--did automatic txn fail?", UNIQUE_TEXT, ((JpaTestEntity) result).getText()); injector.getInstance(UnitOfWork.class).end(); } public void testSimpleTransactionWithMerge() { EntityManager emOrig = injector.getInstance(EntityManager.class); JpaTestEntity entity = injector.getInstance(TransactionalObject.class) .runOperationInTxnWithMerge(); assertNotNull("Entity was not given an id (was not persisted correctly?)", entity.getId()); EntityManager em = injector.getInstance(EntityManager.class); assertFalse(em.getTransaction().isActive()); //test that the data has been stored assertTrue("Em was closed after txn!", em.isOpen()); assertEquals("Em was not kept open across txns", emOrig, em); assertTrue("Merge did not store state or did not return persistent copy", em.contains(entity)); Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT_MERGE).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); assertTrue(result instanceof JpaTestEntity); assertEquals("queried entity did not match--did automatic txn fail?", UNIQUE_TEXT_MERGE, ((JpaTestEntity) result).getText()); injector.getInstance(UnitOfWork.class).end(); } public void disabled_testSimpleTransactionWithMergeAndDF() { EntityManager emOrig = injector.getInstance(EntityManager.class); JpaTestEntity entity = injector.getInstance(TransactionalObject.class) .runOperationInTxnWithMergeForDf(); EntityManager em = injector.getInstance(EntityManager.class); assertFalse("txn was not closed by transactional service", em.getTransaction().isActive()); //test that the data has been stored assertTrue("Em was closed after txn!", em.isOpen()); assertEquals("Em was not kept open across txns", emOrig, em); assertTrue("Merge did not store state or did not return persistent copy", em.contains(entity)); Object result = injector.getInstance(TransactionalObject.class).find(UNIQUE_TEXT_MERGE_FORDF); injector.getInstance(UnitOfWork.class).end(); assertNotNull(result); assertTrue(result instanceof JpaTestEntity); assertEquals("queried entity did not match--did automatic txn fail?", UNIQUE_TEXT_MERGE_FORDF, ((JpaTestEntity) result).getText()); injector.getInstance(UnitOfWork.class).end(); } public void testSimpleTransactionRollbackOnChecked() { try { injector.getInstance(TransactionalObject.class).runOperationInTxnThrowingChecked(); } catch (IOException e) { //ignore injector.getInstance(UnitOfWork.class).end(); } EntityManager em = injector.getInstance(EntityManager.class); assertFalse("Previous EM was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); //test that the data has been stored try { Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail(); } catch (NoResultException e) {} injector.getInstance(UnitOfWork.class).end(); } public void testSimpleTransactionRollbackOnUnchecked() { try { injector.getInstance(TransactionalObject.class).runOperationInTxnThrowingUnchecked(); } catch (RuntimeException re) { //ignore injector.getInstance(UnitOfWork.class).end(); } EntityManager em = injector.getInstance(EntityManager.class); assertFalse("Session was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); try { Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail(); } catch (NoResultException e) {} injector.getInstance(UnitOfWork.class).end(); } public static class TransactionalObject { private final EntityManager em; @Inject public TransactionalObject(EntityManager em) { this.em = em; } @Transactional public void runOperationInTxn() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT); em.persist(entity); } @Transactional public JpaTestEntity runOperationInTxnWithMerge() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT_MERGE); return em.merge(entity); } @Transactional public JpaTestEntity runOperationInTxnWithMergeForDf() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT_MERGE_FORDF); return em.merge(entity); } @Transactional(rollbackOn = IOException.class) public void runOperationInTxnThrowingChecked() throws IOException { JpaTestEntity entity = new JpaTestEntity(); entity.setText(TRANSIENT_UNIQUE_TEXT); em.persist(entity); throw new IOException(); } @Transactional public void runOperationInTxnThrowingUnchecked() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(TRANSIENT_UNIQUE_TEXT); em.persist(entity); throw new IllegalStateException(); } @Finder(query = "from JpaTestEntity where text = :text") public JpaTestEntity find(@Named("text") String text) { return null; } } }guice-3.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerProvisionTest.java0000644000175000017500000000670211443132316033152 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Provider; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import junit.framework.TestCase; /** * A test around providing sessions (starting, closing etc.) * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class EntityManagerProvisionTest extends TestCase { private Injector injector; public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); //startup persistence injector.getInstance(PersistService.class).start(); } public final void tearDown() { injector.getInstance(EntityManagerFactory.class).close(); } public void testEntityManagerLifecyclePerTxn() { //obtain em JpaDao dao = injector.getInstance(JpaDao.class); //obtain same em again (bound to txn) JpaTestEntity te = new JpaTestEntity(); dao.persist(te); //im not sure this hack works... assertFalse("Duplicate entity managers crossing-scope", dao.lastEm.equals(injector.getInstance(EntityManager.class))); //try to start a new em in a new txn dao = injector.getInstance(JpaDao.class); assertFalse("EntityManager wasnt closed and reopened properly around txn" + " (persistent object persists)", dao.contains(te)); } public void testEntityManagerLifecyclePerTxn2() { //obtain em JpaDao dao = injector.getInstance(JpaDao.class); //obtain same em again (bound to txn) JpaTestEntity te = new JpaTestEntity(); dao.persist(te); //im not sure this hack works... assertFalse("Duplicate entity managers crossing-scope", dao.lastEm.equals(injector.getInstance(EntityManager.class))); //try to start a new em in a new txn dao = injector.getInstance(JpaDao.class); assertFalse("EntityManager wasnt closed and reopened properly around txn" + " (persistent object persists)", dao.contains(te)); } public static class JpaDao { private final Provider em; EntityManager lastEm; @Inject public JpaDao(Provider em) { this.em = em; } @Transactional public void persist(T t) { lastEm = em.get(); assertTrue("em is not open!", lastEm.isOpen()); assertTrue("no active txn!", lastEm.getTransaction().isActive()); lastEm.persist(t); assertTrue("Persisting object failed", lastEm.contains(t)); } @Transactional public boolean contains(T t) { if (null == lastEm) { lastEm = em.get(); } return lastEm.contains(t); } } }././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerPerRequestProvisionTest.javaguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerPerRequestProvisionTest0000644000175000017500000000704411443132316034252 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import junit.framework.TestCase; /** * A test around providing sessions (starting, closing etc.) * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class EntityManagerPerRequestProvisionTest extends TestCase { private Injector injector; @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); //startup persistence injector.getInstance(PersistService.class).start(); injector.getInstance(UnitOfWork.class).begin(); } @Override public final void tearDown() { injector.getInstance(UnitOfWork.class).end(); injector.getInstance(EntityManagerFactory.class).close(); } public void testEntityManagerLifecyclePerTxn() { //obtain em JpaDao dao = injector.getInstance(JpaDao.class); //obtain same em again (bound to txn) JpaTestEntity te = new JpaTestEntity(); dao.persist(te); //im not sure this hack works... assertEquals("Entity managers closed inside same thread-scope", injector.getInstance(EntityManager.class), JpaDao.em); //try to start a new em in a new txn dao = injector.getInstance(JpaDao.class); assertTrue("EntityManager was closed and reopened around txn" + " (persistent object does not persist)", dao.contains(te)); } public void testEntityManagerLifecyclePerTxn2() { //obtain em JpaDao dao = injector.getInstance(JpaDao.class); //obtain same em again (bound to txn) JpaTestEntity te = new JpaTestEntity(); dao.persist(te); //im not sure this hack works... assertEquals("Duplicate entity managers crossing-scope", injector.getInstance(EntityManager.class), JpaDao.em); assertEquals("Duplicate entity managers crossing-scope", injector.getInstance(EntityManager.class), JpaDao.em); //try to start a new em in a new txn dao = injector.getInstance(JpaDao.class); assertTrue("EntityManager was closed and reopened around txn" + " (persistent object doesnt persist)", dao.contains(te)); } public static class JpaDao { static EntityManager em; @Inject public JpaDao(EntityManager em) { JpaDao.em = em; } @Transactional public void persist(T t) { assertTrue("em is not open!", em.isOpen()); assertTrue("no active txn!", em.getTransaction().isActive()); em.persist(t); assertTrue("Persisting object failed", em.contains(t)); } @Transactional public boolean contains(T t) { return em.contains(t); } } }guice-3.0/extensions/persist/test/com/google/inject/persist/jpa/JoiningLocalTransactionsTest.java0000644000175000017500000001344511443132316033435 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; import java.io.IOException; import java.util.Date; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.NoResultException; import junit.framework.TestCase; /** * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class JoiningLocalTransactionsTest extends TestCase { private Injector injector; private static final String UNIQUE_TEXT = JoiningLocalTransactionsTest.class + "some unique text" + new Date(); private static final String TRANSIENT_UNIQUE_TEXT = JoiningLocalTransactionsTest.class + "some other unique text" + new Date(); @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); //startup persistence injector.getInstance(PersistService.class).start(); } //cleanup entitymanager in case some of the rollback tests left it in an open state @Override public final void tearDown() { injector.getInstance(UnitOfWork.class).end(); injector.getInstance(EntityManagerFactory.class).close(); } public void testSimpleTransaction() { injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class) .runOperationInTxn(); EntityManager em = injector.getInstance(EntityManager.class); assertFalse("txn was not closed by transactional service", em.getTransaction().isActive()); //test that the data has been stored Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); assertTrue("odd result returned fatal", result instanceof JpaTestEntity); assertEquals("queried entity did not match--did automatic txn fail?", UNIQUE_TEXT, ((JpaTestEntity) result).getText()); } public void testSimpleTransactionRollbackOnChecked() { try { injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class) .runOperationInTxnThrowingChecked(); } catch (IOException e) { //ignore injector.getInstance(UnitOfWork.class).end(); } EntityManager em = injector.getInstance(EntityManager.class); assertFalse("EM was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); //test that the data has been stored try { Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail("a result was returned! rollback sure didnt happen!!!"); } catch (NoResultException e) { } } public void testSimpleTransactionRollbackOnUnchecked() { try { injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class) .runOperationInTxnThrowingUnchecked(); } catch (RuntimeException re) { //ignore injector.getInstance(UnitOfWork.class).end(); } EntityManager em = injector.getInstance(EntityManager.class); assertFalse("Session was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); try { Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail("a result was returned! rollback sure didnt happen!!!"); } catch (NoResultException e) {} } public static class TransactionalObject { private final EntityManager em; @Inject public TransactionalObject(EntityManager em) { this.em = em; } @Transactional public void runOperationInTxn() { runOperationInTxnInternal(); } @Transactional(rollbackOn = IOException.class) public void runOperationInTxnInternal() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT); em.persist(entity); } @Transactional(rollbackOn = IOException.class) public void runOperationInTxnThrowingChecked() throws IOException { runOperationInTxnThrowingCheckedInternal(); } @Transactional private void runOperationInTxnThrowingCheckedInternal() throws IOException { JpaTestEntity entity = new JpaTestEntity(); entity.setText(TRANSIENT_UNIQUE_TEXT); em.persist(entity); throw new IOException(); } @Transactional public void runOperationInTxnThrowingUnchecked() { runOperationInTxnThrowingUncheckedInternal(); } @Transactional(rollbackOn = IOException.class) public void runOperationInTxnThrowingUncheckedInternal() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(TRANSIENT_UNIQUE_TEXT); em.persist(entity); throw new IllegalStateException(); } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerFactoryProvisionTest.javaguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/EntityManagerFactoryProvisionTest.ja0000644000175000017500000000335411443132316034153 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.UnitOfWork; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import junit.framework.TestCase; /** * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class EntityManagerFactoryProvisionTest extends TestCase { private Injector injector; public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); } public final void tearDown() { injector.getInstance(UnitOfWork.class).end(); injector.getInstance(EntityManagerFactory.class).close(); } public void testSessionCreateOnInjection() { assertTrue("SINGLETON VIOLATION " + UnitOfWork.class.getName(), injector.getInstance(UnitOfWork.class) .equals(injector.getInstance(UnitOfWork.class))); //startup persistence injector.getInstance(PersistService.class).start(); //obtain em assertTrue(injector.getInstance(EntityManager.class).isOpen()); } } guice-3.0/extensions/persist/test/com/google/inject/persist/jpa/JpaParentTestEntity.java0000644000175000017500000000271511407727612031564 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import java.util.ArrayList; import java.util.List; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; /** * Created with IntelliJ IDEA. * On: 2/06/2007 * * @author Dhanji R. Prasanna (dhanji@gmail.com) * @since 1.0 */ @Entity public class JpaParentTestEntity { private Long id; private List children = new ArrayList(); @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } @OneToMany public List getChildren() { return children; } public void setChildren(List children) { this.children = children; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/ClassLevelManagedLocalTransactionsTest.javaguice-3.0/extensions/persist/test/com/google/inject/persist/jpa/ClassLevelManagedLocalTransactionsTe0000644000175000017500000001564611526026060034070 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Date; import java.util.List; import javax.persistence.EntityManager; import junit.framework.TestCase; /** * This test asserts class level @Transactional annotation behavior. * * Class-level @Transactional is a shortcut if all non-private methods in the class are meant to be * transactional. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class ClassLevelManagedLocalTransactionsTest extends TestCase { private Injector injector; private static final String UNIQUE_TEXT = "JPAsome unique text88888" + new Date(); private static final String UNIQUE_TEXT_2 = "JPAsome asda unique teasdalsdplasdxt" + new Date(); private static final String TRANSIENT_UNIQUE_TEXT = "JPAsome other unique texaksoksojadasdt" + new Date(); public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); //startup persistence injector.getInstance(PersistService.class).start(); } public void tearDown() { injector.getInstance(PersistService.class).stop(); injector = null; } public void testSimpleTransaction() { injector.getInstance(TransactionalObject.class).runOperationInTxn(); EntityManager session = injector.getInstance(EntityManager.class); assertFalse("EntityManager was not closed by transactional service", session.getTransaction().isActive()); //test that the data has been stored session.getTransaction().begin(); Object result = session.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT).getSingleResult(); session.getTransaction().commit(); assertTrue("odd result returned fatal", result instanceof JpaTestEntity); assertEquals("queried entity did not match--did automatic txn fail?", UNIQUE_TEXT, (((JpaTestEntity) result).getText())); } public void testSimpleTransactionRollbackOnChecked() { try { injector.getInstance(TransactionalObject2.class).runOperationInTxnThrowingChecked(); } catch (IOException e) { //ignore } EntityManager session = injector.getInstance(EntityManager.class); assertFalse("EntityManager was not closed by transactional service (rollback didnt happen?)", session.getTransaction().isActive()); //test that the data has been stored session.getTransaction().begin(); List result = session.createQuery("from JpaTestEntity where text = :text") .setParameter("text", TRANSIENT_UNIQUE_TEXT).getResultList(); session.getTransaction().commit(); assertTrue("a result was returned! rollback sure didnt happen!!!", result.isEmpty()); } public void testSimpleTransactionRollbackOnCheckedExcepting() { Exception ex = null; try { injector.getInstance(TransactionalObject3.class).runOperationInTxnThrowingCheckedExcepting(); fail("Exception was not thrown by test txn-al method!"); } catch (IOException e) { //ignored } EntityManager session = injector.getInstance(EntityManager.class); assertFalse("Txn was not closed by transactional service (commit didnt happen?)", session.getTransaction().isActive()); //test that the data has been stored session.getTransaction().begin(); Object result = session.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT_2).getSingleResult(); session.getTransaction().commit(); assertNotNull("a result was not returned! rollback happened anyway (ignore failed)!!!", result); } public void testSimpleTransactionRollbackOnUnchecked() { try { injector.getInstance(TransactionalObject4.class).runOperationInTxnThrowingUnchecked(); } catch (RuntimeException re) { //ignore } EntityManager session = injector.getInstance(EntityManager.class); assertFalse("EntityManager was not closed by transactional service (rollback didnt happen?)", session.getTransaction().isActive()); //test that the data has been stored session.getTransaction().begin(); List result = session.createQuery("from JpaTestEntity where text = :text") .setParameter("text", TRANSIENT_UNIQUE_TEXT).getResultList(); session.getTransaction().commit(); assertTrue("a result was returned! rollback sure didnt happen!!!", result.isEmpty()); } @Transactional public static class TransactionalObject { @Inject EntityManager session; public void runOperationInTxn() { assertTrue(session.getTransaction().isActive()); JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT); session.persist(entity); } } @Transactional public static class TransactionalObject4 { @Inject EntityManager session; @Transactional public void runOperationInTxnThrowingUnchecked() { assertTrue(session.getTransaction().isActive()); JpaTestEntity entity = new JpaTestEntity(); entity.setText(TRANSIENT_UNIQUE_TEXT); session.persist(entity); throw new IllegalStateException(); } } @Transactional(rollbackOn = IOException.class, ignore = FileNotFoundException.class) public static class TransactionalObject3 { @Inject EntityManager session; public void runOperationInTxnThrowingCheckedExcepting() throws IOException { assertTrue(session.getTransaction().isActive()); JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT_2); session.persist(entity); throw new FileNotFoundException(); } } @Transactional(rollbackOn = IOException.class) public static class TransactionalObject2 { @Inject EntityManager session; public void runOperationInTxnThrowingChecked() throws IOException { assertTrue(session.getTransaction().isActive()); JpaTestEntity entity = new JpaTestEntity(); entity.setText(TRANSIENT_UNIQUE_TEXT); session.persist(entity); throw new IOException(); } } } guice-3.0/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java0000644000175000017500000001420511443132316033367 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; import java.io.IOException; import java.util.Date; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.NoResultException; import junit.framework.TestCase; /** * @author Dhanji R. Prasanna (dhanji@gmail.com) */ public class ManagedLocalTransactionsTest extends TestCase { private Injector injector; private static final String UNIQUE_TEXT = "some unique text" + new Date(); private static final String UNIQUE_TEXT_MERGE = "meRG_Esome unique text" + new Date(); private static final String TRANSIENT_UNIQUE_TEXT = "some other unique text" + new Date(); @Override public void setUp() { injector = Guice.createInjector(new JpaPersistModule("testUnit")); //startup persistence injector.getInstance(PersistService.class).start(); } @Override public final void tearDown() { injector.getInstance(UnitOfWork.class).end(); injector.getInstance(EntityManagerFactory.class).close(); } public void testSimpleTransaction() { injector.getInstance(TransactionalObject.class).runOperationInTxn(); EntityManager em = injector.getInstance(EntityManager.class); assertFalse("txn was not closed by transactional service", em.getTransaction().isActive()); //test that the data has been stored Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); assertTrue("odd result returned fatal", result instanceof JpaTestEntity); assertEquals("queried entity did not match--did automatic txn fail?", UNIQUE_TEXT, ((JpaTestEntity) result).getText()); } public void testSimpleTransactionWithMerge() { JpaTestEntity entity = injector.getInstance(TransactionalObject.class) .runOperationInTxnWithMerge(); EntityManager em = injector.getInstance(EntityManager.class); assertFalse("txn was not closed by transactional service", em.getTransaction().isActive()); //test that the data has been stored assertTrue("Em was closed after txn!", em.isOpen()); Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", UNIQUE_TEXT_MERGE).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); assertTrue(result instanceof JpaTestEntity); assertEquals("queried entity did not match--did automatic txn fail?", UNIQUE_TEXT_MERGE, ((JpaTestEntity) result).getText()); } public void testSimpleTransactionRollbackOnChecked() { try { injector.getInstance(TransactionalObject.class).runOperationInTxnThrowingChecked(); } catch (IOException e) { //ignore injector.getInstance(UnitOfWork.class).end(); } EntityManager em = injector.getInstance(EntityManager.class); assertFalse("Previous EM was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); //test that the data has been stored try { Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail("a result was returned! rollback sure didnt happen!!!"); } catch (NoResultException e) {} } public void testSimpleTransactionRollbackOnUnchecked() { try { injector.getInstance(TransactionalObject.class).runOperationInTxnThrowingUnchecked(); } catch (RuntimeException re) { //ignore injector.getInstance(UnitOfWork.class).end(); } EntityManager em = injector.getInstance(EntityManager.class); assertFalse("Session was not closed by transactional service (rollback didnt happen?)", em.getTransaction().isActive()); try { Object result = em.createQuery("from JpaTestEntity where text = :text") .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult(); injector.getInstance(UnitOfWork.class).end(); fail("a result was returned! rollback sure didnt happen!!!"); } catch (NoResultException e) {} } public static class TransactionalObject { private final EntityManager em; @Inject public TransactionalObject(EntityManager em) { this.em = em; } @Transactional public void runOperationInTxn() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT); em.persist(entity); } @Transactional public JpaTestEntity runOperationInTxnWithMerge() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(UNIQUE_TEXT_MERGE); return em.merge(entity); } @Transactional(rollbackOn = IOException.class) public void runOperationInTxnThrowingChecked() throws IOException { JpaTestEntity entity = new JpaTestEntity(); entity.setText(TRANSIENT_UNIQUE_TEXT); em.persist(entity); throw new IOException(); } @Transactional public void runOperationInTxnThrowingUnchecked() { JpaTestEntity entity = new JpaTestEntity(); entity.setText(TRANSIENT_UNIQUE_TEXT); em.persist(entity); throw new IllegalStateException(); } } }guice-3.0/extensions/persist/test/com/google/inject/persist/jpa/JpaTestEntity.java0000644000175000017500000000336711443132316030405 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; /** @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Entity public class JpaTestEntity { private Long id; private String text; @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getText() { return text; } public void setText(String text) { this.text = text; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } JpaTestEntity that = (JpaTestEntity) o; if (id != null ? !id.equals(that.id) : that.id != null) { return false; } if (text != null ? !text.equals(that.text) : that.text != null) { return false; } return true; } @Override public int hashCode() { int result = id != null ? id.hashCode() : 0; result = 31 * result + (text != null ? text.hashCode() : 0); return result; } } guice-3.0/extensions/persist/test/com/google/inject/persist/AllTests.java0000644000175000017500000000456511407727612026631 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist; import com.google.inject.persist.jpa.ClassLevelManagedLocalTransactionsTest; import com.google.inject.persist.jpa.CustomPropsEntityManagerFactoryProvisionTest; import com.google.inject.persist.jpa.EntityManagerFactoryProvisionTest; import com.google.inject.persist.jpa.EntityManagerPerRequestProvisionTest; import com.google.inject.persist.jpa.EntityManagerProvisionTest; import com.google.inject.persist.jpa.JoiningLocalTransactionsTest; import com.google.inject.persist.jpa.JpaWorkManagerTest; import com.google.inject.persist.jpa.ManagedLocalTransactionsAcrossRequestTest; import com.google.inject.persist.jpa.ManagedLocalTransactionsTest; import com.google.inject.persist.jpa.ManualLocalTransactionsTest; import com.google.inject.persist.jpa.ManualLocalTransactionsWithCustomMatcherTest; import junit.framework.Test; import junit.framework.TestSuite; /** * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public class AllTests { public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(EdslTest.class); suite.addTestSuite(ClassLevelManagedLocalTransactionsTest.class); suite.addTestSuite(CustomPropsEntityManagerFactoryProvisionTest.class); suite.addTestSuite(EntityManagerFactoryProvisionTest.class); suite.addTestSuite(EntityManagerPerRequestProvisionTest.class); suite.addTestSuite(EntityManagerProvisionTest.class); suite.addTestSuite(JoiningLocalTransactionsTest.class); suite.addTestSuite(JpaWorkManagerTest.class); suite.addTestSuite(ManagedLocalTransactionsAcrossRequestTest.class); suite.addTestSuite(ManagedLocalTransactionsTest.class); suite.addTestSuite(ManualLocalTransactionsTest.class); suite.addTestSuite(ManualLocalTransactionsWithCustomMatcherTest.class); return suite; } }guice-3.0/extensions/persist/src/0000755000175000017500000000000011407727614017034 5ustar drazzibdrazzibguice-3.0/extensions/persist/src/log4j.properties0000644000175000017500000000040711407727614022172 0ustar drazzibdrazziblog4j.rootLogger=warn, console log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.Target=System.out log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%p [%c{1}] - %m %n guice-3.0/extensions/persist/src/com/0000755000175000017500000000000011407727612017610 5ustar drazzibdrazzibguice-3.0/extensions/persist/src/com/google/0000755000175000017500000000000011407727614021066 5ustar drazzibdrazzibguice-3.0/extensions/persist/src/com/google/inject/0000755000175000017500000000000011407727614022342 5ustar drazzibdrazzibguice-3.0/extensions/persist/src/com/google/inject/persist/0000755000175000017500000000000011443132322024015 5ustar drazzibdrazzibguice-3.0/extensions/persist/src/com/google/inject/persist/package-info.java0000644000175000017500000000136711471311634027221 0ustar drazzibdrazzib/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Guice Persist: a lightweight persistence library for Guice; this extension requires {@code * guice-persist-3.0.jar}. */ package com.google.inject.persist;guice-3.0/extensions/persist/src/com/google/inject/persist/PersistService.java0000644000175000017500000000304411443132322027633 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist; /** * Persistence provider service. Use this to manage the overall * startup and stop of the persistence module(s). * * TODO(dhanji): Integrate with Service API when appropriate. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public interface PersistService { /** * Starts the underlying persistence engine and makes guice-persist ready for * use. For instance, with JPA, it creates an EntityManagerFactory and may * open connection pools. This method must be called by your code prior to * using any guice-persist or JPA artifacts. If already started, * calling this method does nothing, if already stopped, it also does * nothing. */ void start(); /** * Stops the underlying persistence engine. For instance, with JPA, it * closes the {@code EntityManagerFactory}. If already stopped, calling this * method does nothing. If not yet started, it also does nothing. */ void stop(); } guice-3.0/extensions/persist/src/com/google/inject/persist/PersistModule.java0000644000175000017500000000330311526026236027466 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist; import com.google.inject.AbstractModule; import static com.google.inject.matcher.Matchers.annotatedWith; import static com.google.inject.matcher.Matchers.any; import org.aopalliance.intercept.MethodInterceptor; /** * Install this module to add guice-persist library support for JPA persistence * providers. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public abstract class PersistModule extends AbstractModule { @Override protected final void configure() { configurePersistence(); requireBinding(PersistService.class); requireBinding(UnitOfWork.class); /*if[AOP]*/ // wrapping in an if[AOP] just to allow this to compile in NO_AOP -- it won't be used // class-level @Transacational bindInterceptor(annotatedWith(Transactional.class), any(), getTransactionInterceptor()); // method-level @Transacational bindInterceptor(any(), annotatedWith(Transactional.class), getTransactionInterceptor()); /*end[AOP]*/ } protected abstract void configurePersistence(); protected abstract MethodInterceptor getTransactionInterceptor(); } guice-3.0/extensions/persist/src/com/google/inject/persist/Transactional.java0000644000175000017500000000466511443132322027475 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** *

Any method or class marked with this annotation will be considered for transactionality. * Consult the documentation on http://code.google.com/p/google-guice for detailed semantics. * Marking a method {@code @Transactional} will start a new transaction before the method * executes and commit it after the method returns. *

* If the method throws an exception, the transaction will be rolled back unless * you have specifically requested not to in the {@link #ignore()} clause. *

* Similarly, the set of exceptions that will trigger a rollback can be defined in * the {@link #rollbackOn()} clause. By default, only unchecked exceptions trigger a * rollback. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Transactional { /** * A list of exceptions to rollback on, if thrown by the transactional method. * These exceptions are propagated correctly after a rollback. */ Class[] rollbackOn() default RuntimeException.class; /** * A list of exceptions to not rollback on. A caveat to the rollbackOn clause. * The disjunction of rollbackOn and ignore represents the list of exceptions * that will trigger a rollback. * The complement of rollbackOn and the universal set plus any exceptions in the * ignore set represents the list of exceptions that will trigger a commit. * Note that ignore exceptions take precedence over rollbackOn, but with subtype * granularity. */ Class[] ignore() default { }; } guice-3.0/extensions/persist/src/com/google/inject/persist/finder/0000755000175000017500000000000011443132322025264 5ustar drazzibdrazzibguice-3.0/extensions/persist/src/com/google/inject/persist/finder/package-info.java0000644000175000017500000000013211443132322030447 0ustar drazzibdrazzib/** * Dynamic Finder API for Guice Persist. */ package com.google.inject.persist.finder;guice-3.0/extensions/persist/src/com/google/inject/persist/finder/Finder.java0000644000175000017500000000347111443132322027343 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.finder; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Collection; /** * Marks a method stub as a dynamic finder. The method is intercepted and replaced with the * specified JPAQL query. Provides result auto-boxing and automatic parameter binding. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Finder { /** * Returns the configured named query's name. Specify a named query's name * here. This name is typically specified in your JPA configuration. */ String namedQuery() default ""; /** * Returns the configured query string. Directly specify a JPAQL query here. */ String query() default ""; /** * Returns the configured autoboxing collection class. * Use this clause to specify a collection impl to autobox result lists into. The impl must * have a default no-arg constructor and be a subclass of {@code java.util.Collection}. */ Class returnAs() default Collection.class; }guice-3.0/extensions/persist/src/com/google/inject/persist/finder/MaxResults.java0000644000175000017500000000225011443132322030235 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.finder; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotate any dynamic finder method's integer argument with this to pass in * the maximum size of returned result window. Usefule for paging result sets. * Complement of {@link FirstResult}. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface MaxResults { } guice-3.0/extensions/persist/src/com/google/inject/persist/finder/FirstResult.java0000644000175000017500000000230411443132322030414 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.finder; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotate any dynamic finder method's integer argument with this to pass in * the index of the first result in the result set you are interested in. * Useful for paging result sets. Complemented by {@link MaxResults}. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface FirstResult { } guice-3.0/extensions/persist/src/com/google/inject/persist/finder/DynamicFinder.java0000644000175000017500000000254311443132322030647 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.finder; import java.lang.reflect.Method; /** * Utility that helps you introspect dynamic finder methods. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public final class DynamicFinder { private final Method method; private final Finder finder; public DynamicFinder(Method method) { this.method = method; this.finder = method.getAnnotation(Finder.class); } /** * Returns some metadata if the method is annotated {@code @Finder} or null. * * @param method a method you want to test as a dynamic finder */ public static DynamicFinder from(Method method) { return method.isAnnotationPresent(Finder.class) ? new DynamicFinder(method) : null; } public Finder metadata() { return finder; } } guice-3.0/extensions/persist/src/com/google/inject/persist/PersistFilter.java0000644000175000017500000000636411443132322027470 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist; import com.google.inject.Inject; import com.google.inject.Singleton; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Apply this filter to enable the HTTP Request unit of work and to have * guice-persist manage the lifecycle of active units of work. * The filter automatically starts and stops the relevant {@link PersistService} * upon {@link javax.servlet.Filter#init(javax.servlet.FilterConfig)} and * {@link javax.servlet.Filter#destroy()} respectively. * *

To be able to use the open session-in-view pattern (i.e. work per request), * register this filter once in your Guice {@code ServletModule}. It is * important that you register this filter before any other filter. * * For multiple providers, you should register this filter once per provider, inside * a private module for each persist module installed (this must be the same private * module where the specific persist module is itself installed). * *

* Example configuration: *

{@code
 *  public class MyModule extends ServletModule {
 *    public void configureServlets() {
 *      filter("/*").through(PersistFilter.class);
 *
 *      serve("/index.html").with(MyHtmlServlet.class);
 *      // Etc.
 *    }
 *  }
 * }
*

* This filter is thread safe and allows you to create injectors concurrently * and deploy multiple guice-persist modules within the same injector, or even * multiple injectors with persist modules withing the same JVM or web app. *

* This filter requires the Guice Servlet extension. * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Singleton public final class PersistFilter implements Filter { private final UnitOfWork unitOfWork; private final PersistService persistService; @Inject public PersistFilter(UnitOfWork unitOfWork, PersistService persistService) { this.unitOfWork = unitOfWork; this.persistService = persistService; } public void init(FilterConfig filterConfig) throws ServletException { persistService.start(); } public void destroy() { persistService.stop(); } public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException { unitOfWork.begin(); try { filterChain.doFilter(servletRequest, servletResponse); } finally { unitOfWork.end(); } } } guice-3.0/extensions/persist/src/com/google/inject/persist/jpa/0000755000175000017500000000000011510705016024570 5ustar drazzibdrazzibguice-3.0/extensions/persist/src/com/google/inject/persist/jpa/package-info.java0000644000175000017500000000014511443132322027756 0ustar drazzibdrazzib/** * guice-persist's Java Persistence API (JPA) support. */ package com.google.inject.persist.jpa;guice-3.0/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistService.java0000644000175000017500000000731311461631440031050 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.internal.util.Nullable; import com.google.inject.internal.util.Preconditions; import com.google.inject.persist.PersistService; import com.google.inject.persist.UnitOfWork; import java.util.Properties; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; /** * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Singleton class JpaPersistService implements Provider, UnitOfWork, PersistService { private final ThreadLocal entityManager = new ThreadLocal(); private final String persistenceUnitName; private final Properties persistenceProperties; @Inject public JpaPersistService(@Jpa String persistenceUnitName, @Nullable @Jpa Properties persistenceProperties) { this.persistenceUnitName = persistenceUnitName; this.persistenceProperties = persistenceProperties; } public EntityManager get() { if (!isWorking()) { begin(); } EntityManager em = entityManager.get(); Preconditions.checkState(null != em, "Requested EntityManager outside work unit. " + "Try calling UnitOfWork.begin() first, or use a PersistFilter if you " + "are inside a servlet environment."); return em; } public boolean isWorking() { return entityManager.get() != null; } public void begin() { Preconditions.checkState(null == entityManager.get(), "Work already begun on this thread. Looks like you have called UnitOfWork.begin() twice" + " without a balancing call to end() in between."); entityManager.set(emFactory.createEntityManager()); } public void end() { EntityManager em = entityManager.get(); // Let's not penalize users for calling end() multiple times. if (null == em) { return; } em.close(); entityManager.remove(); } private volatile EntityManagerFactory emFactory; public synchronized void start() { Preconditions.checkState(null == emFactory, "Persistence service was already initialized."); if (null != persistenceProperties) { this.emFactory = Persistence .createEntityManagerFactory(persistenceUnitName, persistenceProperties); } else { this.emFactory = Persistence.createEntityManagerFactory(persistenceUnitName); } } public synchronized void stop() { Preconditions.checkState(emFactory.isOpen(), "Persistence service was already shut down."); emFactory.close(); } @Singleton public static class EntityManagerFactoryProvider implements Provider { private final JpaPersistService emProvider; @Inject public EntityManagerFactoryProvider(JpaPersistService emProvider) { this.emProvider = emProvider; } public EntityManagerFactory get() { assert null != emProvider.emFactory; return emProvider.emFactory; } } } guice-3.0/extensions/persist/src/com/google/inject/persist/jpa/JpaPersistModule.java0000644000175000017500000001337711460132762030706 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Preconditions; import com.google.inject.persist.PersistModule; import com.google.inject.persist.PersistService; import com.google.inject.persist.UnitOfWork; import com.google.inject.persist.finder.DynamicFinder; import com.google.inject.persist.finder.Finder; import com.google.inject.util.Providers; import java.lang.reflect.AccessibleObject; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.List; import java.util.Properties; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * JPA provider for guice persist. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public final class JpaPersistModule extends PersistModule { private final String jpaUnit; public JpaPersistModule(String jpaUnit) { Preconditions.checkArgument(null != jpaUnit && jpaUnit.length() > 0, "JPA unit name must be a non-empty string."); this.jpaUnit = jpaUnit; } private Properties properties; private MethodInterceptor transactionInterceptor; @Override protected void configurePersistence() { bindConstant().annotatedWith(Jpa.class).to(jpaUnit); if (null != properties) { bind(Properties.class).annotatedWith(Jpa.class).toInstance(properties); } else { bind(Properties.class).annotatedWith(Jpa.class) .toProvider(Providers.of(null)); } bind(JpaPersistService.class).in(Singleton.class); bind(PersistService.class).to(JpaPersistService.class); bind(UnitOfWork.class).to(JpaPersistService.class); bind(EntityManager.class).toProvider(JpaPersistService.class); bind(EntityManagerFactory.class) .toProvider(JpaPersistService.EntityManagerFactoryProvider.class); transactionInterceptor = new JpaLocalTxnInterceptor(); requestInjection(transactionInterceptor); // Bind dynamic finders. for (Class finder : dynamicFinders) { bindFinder(finder); } } @Override protected MethodInterceptor getTransactionInterceptor() { return transactionInterceptor; } /** * Configures the JPA persistence provider with a set of properties. * * @param properties A set of name value pairs that configure a JPA persistence * provider as per the specification. */ public JpaPersistModule properties(Properties properties) { this.properties = properties; return this; } private final List> dynamicFinders = Lists.newArrayList(); /** * Adds an interface to this module to use as a dynamic finder. * * @param iface Any interface type whose methods are all dynamic finders. */ public JpaPersistModule addFinder(Class iface) { dynamicFinders.add(iface); return this; } private void bindFinder(Class iface) { if (!isDynamicFinderValid(iface)) { return; } InvocationHandler finderInvoker = new InvocationHandler() { @Inject JpaFinderProxy finderProxy; public Object invoke(final Object thisObject, final Method method, final Object[] args) throws Throwable { // Don't intercept non-finder methods like equals and hashcode. if (!method.isAnnotationPresent(Finder.class)) { // NOTE(dhanji): This is not ideal, we are using the invocation handler's equals // and hashcode as a proxy (!) for the proxy's equals and hashcode. return method.invoke(this, args); } return finderProxy.invoke(new MethodInvocation() { public Method getMethod() { return method; } public Object[] getArguments() { return null == args ? new Object[0] : args; } public Object proceed() throws Throwable { return method.invoke(thisObject, args); } public Object getThis() { throw new UnsupportedOperationException("Bottomless proxies don't expose a this."); } public AccessibleObject getStaticPart() { throw new UnsupportedOperationException(); } }); } }; requestInjection(finderInvoker); @SuppressWarnings("unchecked") // Proxy must produce instance of type given. T proxy = (T) Proxy .newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] { iface }, finderInvoker); bind(iface).toInstance(proxy); } private boolean isDynamicFinderValid(Class iface) { boolean valid = true; if (!iface.isInterface()) { addError(iface + " is not an interface. Dynamic Finders must be interfaces."); valid = false; } for (Method method : iface.getMethods()) { DynamicFinder finder = DynamicFinder.from(method); if (null == finder) { addError("Dynamic Finder methods must be annotated with @Finder, but " + iface + "." + method.getName() + " was not"); valid = false; } } return valid; } } guice-3.0/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java0000644000175000017500000001167511443132322032042 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Inject; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; import java.lang.reflect.Method; import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * @author Dhanji R. Prasanna (dhanji@gmail.com) */ class JpaLocalTxnInterceptor implements MethodInterceptor { @Inject private final JpaPersistService emProvider = null; @Inject private final UnitOfWork unitOfWork = null; @Transactional private static class Internal {} // Tracks if the unit of work was begun implicitly by this transaction. private final ThreadLocal didWeStartWork = new ThreadLocal(); public Object invoke(MethodInvocation methodInvocation) throws Throwable { // Should we start a unit of work? if (!emProvider.isWorking()) { emProvider.begin(); didWeStartWork.set(true); } Transactional transactional = readTransactionMetadata(methodInvocation); EntityManager em = this.emProvider.get(); // Allow 'joining' of transactions if there is an enclosing @Transactional method. if (em.getTransaction().isActive()) { return methodInvocation.proceed(); } final EntityTransaction txn = em.getTransaction(); txn.begin(); Object result; try { result = methodInvocation.proceed(); } catch (Exception e) { //commit transaction only if rollback didnt occur if (rollbackIfNecessary(transactional, e, txn)) { txn.commit(); } //propagate whatever exception is thrown anyway throw e; } finally { // Close the em if necessary (guarded so this code doesn't run unless catch fired). if (null != didWeStartWork.get() && !txn.isActive()) { didWeStartWork.remove(); unitOfWork.end(); } } //everything was normal so commit the txn (do not move into try block above as it // interferes with the advised method's throwing semantics) try { txn.commit(); } finally { //close the em if necessary if (null != didWeStartWork.get() ) { didWeStartWork.remove(); unitOfWork.end(); } } //or return result return result; } // TODO(dhanji): Cache this method's results. private Transactional readTransactionMetadata(MethodInvocation methodInvocation) { Transactional transactional; Method method = methodInvocation.getMethod(); Class targetClass = methodInvocation.getThis().getClass(); transactional = method.getAnnotation(Transactional.class); if (null == transactional) { // If none on method, try the class. transactional = targetClass.getAnnotation(Transactional.class); } if (null == transactional) { // If there is no transactional annotation present, use the default transactional = Internal.class.getAnnotation(Transactional.class); } return transactional; } /** * Returns True if rollback DID NOT HAPPEN (i.e. if commit should continue). * * @param transactional The metadata annotaiton of the method * @param e The exception to test for rollback * @param txn A JPA Transaction to issue rollbacks on */ private boolean rollbackIfNecessary(Transactional transactional, Exception e, EntityTransaction txn) { boolean commit = true; //check rollback clauses for (Class rollBackOn : transactional.rollbackOn()) { //if one matched, try to perform a rollback if (rollBackOn.isInstance(e)) { commit = false; //check ignore clauses (supercedes rollback clause) for (Class exceptOn : transactional.ignore()) { //An exception to the rollback clause was found, DON'T rollback // (i.e. commit and throw anyway) if (exceptOn.isInstance(e)) { commit = true; break; } } //rollback only if nothing matched the ignore check if (!commit) { txn.rollback(); } //otherwise continue to commit break; } } return commit; } } guice-3.0/extensions/persist/src/com/google/inject/persist/jpa/JpaFinderProxy.java0000644000175000017500000002504111510705016030341 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.internal.util.MapMaker; import com.google.inject.name.Named; import com.google.inject.persist.finder.Finder; import com.google.inject.persist.finder.FirstResult; import com.google.inject.persist.finder.MaxResults; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collection; import java.util.List; import java.util.Map; import javax.persistence.EntityManager; import javax.persistence.Query; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * TODO(dhanji): Make this work!! * * @author Dhanji R. Prasanna (dhanji@gmail.com) */ @Singleton class JpaFinderProxy implements MethodInterceptor { private final Map finderCache = new MapMaker().weakKeys().makeMap(); private final Provider emProvider; @Inject public JpaFinderProxy(Provider emProvider) { this.emProvider = emProvider; } public Object invoke(MethodInvocation methodInvocation) throws Throwable { EntityManager em = emProvider.get(); //obtain a cached finder descriptor (or create a new one) JpaFinderProxy.FinderDescriptor finderDescriptor = getFinderDescriptor(methodInvocation); Object result = null; //execute as query (named params or otherwise) Query jpaQuery = finderDescriptor.createQuery(em); if (finderDescriptor.isBindAsRawParameters) { bindQueryRawParameters(jpaQuery, finderDescriptor, methodInvocation.getArguments()); } else { bindQueryNamedParameters(jpaQuery, finderDescriptor, methodInvocation.getArguments()); } //depending upon return type, decorate or return the result as is if (JpaFinderProxy.ReturnType.PLAIN.equals(finderDescriptor.returnType)) { result = jpaQuery.getSingleResult(); } else if (JpaFinderProxy.ReturnType.COLLECTION.equals(finderDescriptor.returnType)) { result = getAsCollection(finderDescriptor, jpaQuery.getResultList()); } else if (JpaFinderProxy.ReturnType.ARRAY.equals(finderDescriptor.returnType)) { result = jpaQuery.getResultList().toArray(); } return result; } private Object getAsCollection(JpaFinderProxy.FinderDescriptor finderDescriptor, List results) { Collection collection; try { collection = (Collection) finderDescriptor.returnCollectionTypeConstructor.newInstance(); } catch (InstantiationException e) { throw new RuntimeException( "Specified collection class of Finder's returnAs could not be instantated: " + finderDescriptor.returnCollectionType, e); } catch (IllegalAccessException e) { throw new RuntimeException( "Specified collection class of Finder's returnAs could not be instantated (do not have access privileges): " + finderDescriptor.returnCollectionType, e); } catch (InvocationTargetException e) { throw new RuntimeException( "Specified collection class of Finder's returnAs could not be instantated (it threw an exception): " + finderDescriptor.returnCollectionType, e); } collection.addAll(results); return collection; } private void bindQueryNamedParameters(Query jpaQuery, JpaFinderProxy.FinderDescriptor descriptor, Object[] arguments) { for (int i = 0; i < arguments.length; i++) { Object argument = arguments[i]; Object annotation = descriptor.parameterAnnotations[i]; if (null == annotation) //noinspection UnnecessaryContinue { continue; //skip param as it's not bindable } else if (annotation instanceof Named) { Named named = (Named) annotation; jpaQuery.setParameter(named.value(), argument); } else if (annotation instanceof javax.inject.Named) { javax.inject.Named named = (javax.inject.Named) annotation; jpaQuery.setParameter(named.value(), argument); } else if (annotation instanceof FirstResult) { jpaQuery.setFirstResult((Integer) argument); } else if (annotation instanceof MaxResults) { jpaQuery.setMaxResults((Integer) argument); } } } private void bindQueryRawParameters(Query jpaQuery, JpaFinderProxy.FinderDescriptor descriptor, Object[] arguments) { for (int i = 0, index = 1; i < arguments.length; i++) { Object argument = arguments[i]; Object annotation = descriptor.parameterAnnotations[i]; if (null == annotation) { //bind it as a raw param (1-based index, yes I know its different from Hibernate, blargh) jpaQuery.setParameter(index, argument); index++; } else if (annotation instanceof FirstResult) { jpaQuery.setFirstResult((Integer) argument); } else if (annotation instanceof MaxResults) { jpaQuery.setMaxResults((Integer) argument); } } } private JpaFinderProxy.FinderDescriptor getFinderDescriptor(MethodInvocation invocation) { Method method = invocation.getMethod(); JpaFinderProxy.FinderDescriptor finderDescriptor = finderCache.get(method); if (null != finderDescriptor) { return finderDescriptor; } //otherwise reflect and cache finder info... finderDescriptor = new JpaFinderProxy.FinderDescriptor(); //determine return type finderDescriptor.returnClass = invocation.getMethod().getReturnType(); finderDescriptor.returnType = determineReturnType(finderDescriptor.returnClass); //determine finder query characteristics Finder finder = invocation.getMethod().getAnnotation(Finder.class); String query = finder.query(); if (!"".equals(query.trim())) { finderDescriptor.setQuery(query); } else { finderDescriptor.setNamedQuery(finder.namedQuery()); } //determine parameter annotations Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Object[] discoveredAnnotations = new Object[parameterAnnotations.length]; for (int i = 0; i < parameterAnnotations.length; i++) { Annotation[] annotations = parameterAnnotations[i]; //each annotation per param for (Annotation annotation : annotations) { //discover the named, first or max annotations then break out Class annotationType = annotation.annotationType(); if (Named.class.equals(annotationType) || javax.inject.Named.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; finderDescriptor.isBindAsRawParameters = false; break; } else if (FirstResult.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; break; } else if (MaxResults.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; break; } //leave as null for no binding } } //set the discovered set to our finder cache object finderDescriptor.parameterAnnotations = discoveredAnnotations; //discover the returned collection implementation if this finder returns a collection if (JpaFinderProxy.ReturnType.COLLECTION.equals(finderDescriptor.returnType) && finderDescriptor.returnClass != Collection.class) { finderDescriptor.returnCollectionType = finder.returnAs(); try { finderDescriptor.returnCollectionTypeConstructor = finderDescriptor.returnCollectionType .getConstructor(); finderDescriptor.returnCollectionTypeConstructor.setAccessible(true); //UGH! } catch (NoSuchMethodException e) { throw new RuntimeException( "Finder's collection return type specified has no default constructor! returnAs: " + finderDescriptor.returnCollectionType, e); } } //cache it cacheFinderDescriptor(method, finderDescriptor); return finderDescriptor; } /** * writes to a chm (used to provide copy-on-write but this is bettah!) * * @param method The key * @param finderDescriptor The descriptor to cache */ private void cacheFinderDescriptor(Method method, FinderDescriptor finderDescriptor) { //write to concurrent map finderCache.put(method, finderDescriptor); } private JpaFinderProxy.ReturnType determineReturnType(Class returnClass) { if (Collection.class.isAssignableFrom(returnClass)) { return JpaFinderProxy.ReturnType.COLLECTION; } else if (returnClass.isArray()) { return JpaFinderProxy.ReturnType.ARRAY; } return JpaFinderProxy.ReturnType.PLAIN; } /** * A wrapper data class that caches information about a finder method. */ private static class FinderDescriptor { private volatile boolean isKeyedQuery = false; volatile boolean isBindAsRawParameters = true; //should we treat the query as having ? instead of :named params volatile JpaFinderProxy.ReturnType returnType; volatile Class returnClass; volatile Class returnCollectionType; volatile Constructor returnCollectionTypeConstructor; volatile Object[] parameterAnnotations; //contract is: null = no bind, @Named = param, @FirstResult/@MaxResults for paging private String query; private String name; void setQuery(String query) { this.query = query; } void setNamedQuery(String name) { this.name = name; isKeyedQuery = true; } public boolean isKeyedQuery() { return isKeyedQuery; } Query createQuery(EntityManager em) { return isKeyedQuery ? em.createNamedQuery(name) : em.createQuery(query); } } private static enum ReturnType { PLAIN, COLLECTION, ARRAY } } guice-3.0/extensions/persist/src/com/google/inject/persist/jpa/Jpa.java0000644000175000017500000000170011443132322026142 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist.jpa; import com.google.inject.BindingAnnotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * A binding annotation for internal JPA module properties. * * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @Retention(RetentionPolicy.RUNTIME) @BindingAnnotation @interface Jpa {} guice-3.0/extensions/persist/src/com/google/inject/persist/UnitOfWork.java0000644000175000017500000000451611443132322026735 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.persist; /** * This interface is used to gain manual control over the unit of work. This is mostly to do * work in non-request, non-transactional threads. Or where more fine-grained control over the unit * of work is required. Starting and ending a unit of work directly corresponds to opening and * closing a {@code Session}, {@code EntityManager} or {@code ObjectContainer} respectively. *

The * Unit of Work referred to by UnitOfWork will always be local to the calling thread. Be careful to * end() in a finally block. Neither JPA, nor Hibernate supports threadsafe sessions (reasoning * behind thread-locality of Unit of Work semantics). * *

    *
  • Using UnitOfWork with the PersistFilter inside a request is not recommended.
  • *
  • Using UnitOfWork with session-per-txn strategy is not terribly clever either.
  • *
  • Using UnitOfWork with session-per-request strategy but *outside* a request (i.e. in a * background or bootstrap thread) is probably a good use case.
  • *
* * @author Dhanji R. Prasanna (dhanji@gmail com) */ public interface UnitOfWork { /** * Starts a Unit Of Work. Underneath, causes a session to the data layer to be opened. If there * is already one open, the invocation will do nothing. In this way, you can define arbitrary * units-of-work that nest within one another safely. * * Transaction semantics are not affected. */ void begin(); /** * Declares an end to the current Unit of Work. Underneath, causes any open session to the data * layer to close. If there is no Unit of work open, then the call returns silently. You can * safely invoke end() repeatedly. *

* Transaction semantics are not affected. */ void end(); } guice-3.0/extensions/jndi/0000755000175000017500000000000011542727754015505 5ustar drazzibdrazzibguice-3.0/extensions/jndi/build/0000755000175000017500000000000011542727754016604 5ustar drazzibdrazzibguice-3.0/extensions/jndi/build/META-INF/0000755000175000017500000000000011542727754017744 5ustar drazzibdrazzibguice-3.0/extensions/jndi/build/META-INF/MANIFEST.MF0000644000175000017500000000120611542727752021373 0ustar drazzibdrazzibManifest-Version: 1.0 Export-Package: com.google.inject.jndi;version="1.3" Bundle-Name: guice-jndi Created-By: 1.6.0_23 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-Copyright: Copyright (C) 2006 Google Inc. Bundle-Vendor: Google, Inc. Bundle-Version: 3.0 Bundle-ManifestVersion: 2 Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-Description: Guice is a lightweight dependency injection framew ork for Java 5 and above Bundle-DocURL: http://code.google.com/p/google-guice/ Import-Package: com.google.inject,javax.naming Bundle-SymbolicName: com.google.inject.jndi guice-3.0/extensions/jndi/build/dist/0000755000175000017500000000000011542727754017547 5ustar drazzibdrazzibguice-3.0/extensions/jndi/build/classes/0000755000175000017500000000000011542727754020241 5ustar drazzibdrazzibguice-3.0/extensions/jndi/build/classes/com/0000755000175000017500000000000011542727754021017 5ustar drazzibdrazzibguice-3.0/extensions/jndi/build/classes/com/google/0000755000175000017500000000000011542727754022273 5ustar drazzibdrazzibguice-3.0/extensions/jndi/build/classes/com/google/inject/0000755000175000017500000000000011542727754023547 5ustar drazzibdrazzibguice-3.0/extensions/jndi/build/classes/com/google/inject/jndi/0000755000175000017500000000000011542727754024473 5ustar drazzibdrazzibguice-3.0/extensions/jndi/pom.xml0000644000175000017500000000105211460132762017004 0ustar drazzibdrazzib 4.0.0 com.google.inject.extensions extensions-parent 3.0-SNAPSHOT guice-jndi Google Guice - Extensions - JNDI guice-3.0/extensions/jndi/build.xml0000644000175000017500000000123711461503350017311 0ustar drazzibdrazzib guice-3.0/extensions/jndi/jndi.iml0000644000175000017500000000076311214265006017121 0ustar drazzibdrazzib guice-3.0/extensions/jndi/build.properties0000644000175000017500000000013211461376774020720 0ustar drazzibdrazziblib.dir=../../lib src.dir=src test.dir=test build.dir=build module=com.google.inject.jndi guice-3.0/extensions/jndi/src/0000755000175000017500000000000011214265006016253 5ustar drazzibdrazzibguice-3.0/extensions/jndi/src/com/0000755000175000017500000000000011214265006017031 5ustar drazzibdrazzibguice-3.0/extensions/jndi/src/com/google/0000755000175000017500000000000011214265006020305 5ustar drazzibdrazzibguice-3.0/extensions/jndi/src/com/google/inject/0000755000175000017500000000000011214265006021561 5ustar drazzibdrazzibguice-3.0/extensions/jndi/src/com/google/inject/jndi/0000755000175000017500000000000011214265006022505 5ustar drazzibdrazzibguice-3.0/extensions/jndi/src/com/google/inject/jndi/package-info.java0000644000175000017500000000130411461123406025673 0ustar drazzibdrazzib/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * JNDI integration; this extension requires {@code guice-jndi-3.0.jar}. */ package com.google.inject.jndi;guice-3.0/extensions/jndi/src/com/google/inject/jndi/JndiIntegration.java0000644000175000017500000000330311214265006026437 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.jndi; import com.google.inject.Inject; import com.google.inject.Provider; import javax.naming.Context; import javax.naming.NamingException; /** * Integrates Guice with JNDI. Requires a binding to * {@link javax.naming.Context}. * * @author crazybob@google.com (Bob Lee) */ public class JndiIntegration { private JndiIntegration() {} /** * Creates a provider which looks up objects in JNDI using the given name. * Example usage: * *

   * bind(DataSource.class).toProvider(fromJndi(DataSource.class, "java:..."));
   * 
*/ public static Provider fromJndi(Class type, String name) { return new JndiProvider(type, name); } static class JndiProvider implements Provider { @Inject Context context; final Class type; final String name; public JndiProvider(Class type, String name) { this.type = type; this.name = name; } public T get() { try { return type.cast(context.lookup(name)); } catch (NamingException e) { throw new RuntimeException(e); } } } } guice-3.0/pom.xml0000644000175000017500000003127011512304574013666 0ustar drazzibdrazzib 4.0.0 com.google google 5 pom com.google.inject guice-parent 3.0-SNAPSHOT Google Guice Guice is a lightweight dependency injection framework for Java 5 and above http://code.google.com/p/google-guice/ 2006 Google, Inc. http://www.google.com Guice Users List http://groups.google.com/group/google-guice/topics http://groups.google.com/group/google-guice/subscribe http://groups.google.com/group/google-guice/subscribe http://groups.google.com/group/google-guice/post Guice Developers List http://groups.google.com/group/google-guice-dev/topics http://groups.google.com/group/google-guice-dev/subscribe http://groups.google.com/group/google-guice-dev/subscribe http://groups.google.com/group/google-guice-dev/post scm:svn:http://google-guice.googlecode.com/svn/trunk scm:svn:https://google-guice.googlecode.com/svn/trunk http://code.google.com/p/google-guice/source/browse Google Code http://code.google.com/p/google-guice/issues/ Hudson https://grid.sonatype.org/ci/job/Google-Guice/ The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo core extensions 3.0 1.3 UTF-8 true true org.testng testng 5.11 jdk15 test ${project.basedir}/src false ${project.basedir}/src **/*.java ${project.basedir}/test false ${project.basedir}/test **/*.java maven-remote-resources-plugin 1.1 process org.apache:apache-jar-resource-bundle:1.4 maven-compiler-plugin 2.3.2 org.codehaus.mojo animal-sniffer-maven-plugin 1.6 org.codehaus.mojo.signature java15 1.0 check-java-1.5-compat process-classes check org.sonatype.plugins jarjar-maven-plugin 1.3 net.sf.cglib.* com.google.inject.internal.cglib.$@1 net.sf.cglib.**.* com.google.inject.internal.cglib.@1.$@2 org.objectweb.asm.* com.google.inject.internal.asm.$@1 org.objectweb.asm.**.* com.google.inject.internal.asm.@1.$@2 com.google.inject.internal.util.* com.google.inject.internal.util.$@1 com.google.inject.internal.util.**.* com.google.inject.internal.util.@1.$@2 com.google.inject.** com.googlecode.** jarjar-classes process-test-classes jarjar {classes} jarjar-test-classes process-test-classes jarjar {test-classes} maven-surefire-plugin 2.5 true org.apache.felix maven-bundle-plugin 2.1.0 com.google.inject <_include>-${project.basedir}/build.properties Copyright (C) 2006 Google Inc. http://code.google.com/p/google-guice/ ${project.artifactId} $(module) J2SE-1.5,JavaSE-1.6 !com.google.inject.*,* <_exportcontents>!*.internal.*,$(module).*;version=${guice.api.version} <_versionpolicy>[$(version;==;$(@)),$(version;+;$(@))) <_nouses>true <_removeheaders> Embed-Dependency,Embed-Transitive, Built-By,Tool,Created-By,Build-Jdk, Originally-Created-By,Archiver-Version, Include-Resource,Private-Package, Ignore-Package,Bnd-LastModified prepare-package manifest maven-jar-plugin 2.3.1 ${project.build.outputDirectory}/META-INF/MANIFEST.MF false package test-jar maven-javadoc-plugin 2.7 maven-source-plugin 2.1.2 maven-gpg-plugin 1.1 maven-release-plugin 2.1 true maven-deploy-plugin 2.5 sonatype-grid forge-releases http://repository.sonatype.org:8081/service/local/staging/deploy/maven2 forge-snapshots http://repository.sonatype.org/content/repositories/snapshots ${forgeReleaseId} ${forgeReleaseUrl} ${forgeSnapshotId} ${forgeSnapshotUrl} guice-3.0/examples/0000755000175000017500000000000011442650764014173 5ustar drazzibdrazzibguice-3.0/examples/examples.iml0000644000175000017500000000134111442650764016513 0ustar drazzibdrazzib guice-3.0/examples/src/0000755000175000017500000000000011214265036014751 5ustar drazzibdrazzibguice-3.0/examples/src/example/0000755000175000017500000000000011214265036016404 5ustar drazzibdrazzibguice-3.0/examples/src/example/xml/0000755000175000017500000000000011254111602017175 5ustar drazzibdrazzibguice-3.0/examples/src/example/xml/FlashMemory.java0000644000175000017500000000031611254111602022266 0ustar drazzibdrazzibpackage example.xml; import java.util.Collections; public class FlashMemory implements Contacts { public Iterable findByName(String name) { return Collections.emptyList(); } } guice-3.0/examples/src/example/xml/Contacts.java0000644000175000017500000000014611254111602021617 0ustar drazzibdrazzibpackage example.xml; public interface Contacts { Iterable findByName(String name); } guice-3.0/examples/src/example/xml/FromSim.java0000644000175000017500000000025411254111602021415 0ustar drazzibdrazzibpackage example.xml; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.*; @Retention(RUNTIME) public @interface FromSim {} guice-3.0/examples/src/example/xml/Contact.java0000644000175000017500000000006511254111602021434 0ustar drazzibdrazzibpackage example.xml; public class Contact { } guice-3.0/examples/src/example/xml/Phone.java0000644000175000017500000000033711254111602021114 0ustar drazzibdrazzibpackage example.xml; public class Phone { Contacts contacts; public void setContacts(Contacts contacts) { this.contacts = contacts; } public Contacts getContacts() { return contacts; } } guice-3.0/examples/src/example/xml/XmlBeanModule.java0000644000175000017500000001331711254111602022541 0ustar drazzibdrazzibpackage example.xml; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.Binder; import java.io.InputStreamReader; import java.io.Reader; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.Locator; import safesax.Element; import safesax.ElementListener; import safesax.Parsers; import safesax.RootElement; import safesax.StartElementListener; public class XmlBeanModule implements Module { final URL xmlUrl; Locator locator; Binder originalBinder; BeanBuilder beanBuilder; public XmlBeanModule(URL xmlUrl) { this.xmlUrl = xmlUrl; } public void configure(Binder binder) { this.originalBinder = binder; try { RootElement beans = new RootElement("beans"); locator = beans.getLocator(); Element bean = beans.getChild("bean"); bean.setElementListener(new BeanListener()); Element property = bean.getChild("property"); property.setStartElementListener(new PropertyListener()); Reader in = new InputStreamReader(xmlUrl.openStream()); Parsers.parse(in, beans.getContentHandler()); } catch (Exception e) { originalBinder.addError(e); } } /** Handles "binding" elements. */ class BeanListener implements ElementListener { public void start(final Attributes attributes) { Binder sourced = originalBinder.withSource(xmlSource()); String typeString = attributes.getValue("type"); // Make sure 'type' is present. if (typeString == null) { sourced.addError("Missing 'type' attribute."); return; } // Resolve 'type'. Class type; try { type = Class.forName(typeString); } catch (ClassNotFoundException e) { sourced.addError(e); return; } // Look for a no-arg constructor. try { type.getConstructor(); } catch (NoSuchMethodException e) { sourced.addError("%s doesn't have a no-arg constructor."); return; } // Create a bean builder for the given type. beanBuilder = new BeanBuilder(type); } public void end() { if (beanBuilder != null) { beanBuilder.build(); beanBuilder = null; } } } /** Handles "property" elements. */ class PropertyListener implements StartElementListener { public void start(final Attributes attributes) { Binder sourced = originalBinder.withSource(xmlSource()); if (beanBuilder == null) { // We must have already run into an error. return; } // Check for 'name'. String name = attributes.getValue("name"); if (name == null) { sourced.addError("Missing attribute name."); return; } Class type = beanBuilder.type; // Find setter method for the given property name. String setterName = "set" + capitalize(name); Method setter = null; for (Method method : type.getMethods()) { if (method.getName().equals(setterName)) { setter = method; break; } } if (setter == null) { sourced.addError("%s.%s() not found.", type.getName(), setterName); return; } // Validate number of parameters. Type[] parameterTypes = setter.getGenericParameterTypes(); if (parameterTypes.length != 1) { sourced.addError("%s.%s() must take one argument.", setterName, type.getName()); return; } // Add property descriptor to builder. Provider provider = sourced.getProvider(Key.get(parameterTypes[0])); beanBuilder.properties.add( new Property(setter, provider)); } } static String capitalize(String s) { return Character.toUpperCase(s.charAt(0)) + s.substring(1); } static class Property { final Method setter; final Provider provider; Property(Method setter, Provider provider) { this.setter = setter; this.provider = provider; } void setOn(Object o) { try { setter.invoke(o, provider.get()); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } } class BeanBuilder { final List properties = new ArrayList(); final Class type; BeanBuilder(Class type) { this.type = type; } void build() { addBinding(type); } void addBinding(Class type) { originalBinder.withSource(xmlSource()) .bind(type).toProvider(new BeanProvider(type, properties)); } } static class BeanProvider implements Provider { final Class type; final List properties; BeanProvider(Class type, List properties) { this.type = type; this.properties = properties; } public T get() { try { T t = type.newInstance(); for (Property property : properties) { property.setOn(t); } return t; } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } Object xmlSource() { return xmlUrl + ":" + locator.getLineNumber(); } } guice-3.0/examples/src/example/xml/phone.xml0000644000175000017500000000014011214265036021032 0ustar drazzibdrazzib guice-3.0/examples/src/example/xml/FromFlash.java0000644000175000017500000000025411254111602021722 0ustar drazzibdrazzibpackage example.xml; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.*; @Retention(RUNTIME) public @interface FromFlash {}guice-3.0/examples/src/example/xml/SimCard.java0000644000175000017500000000031011254111602021354 0ustar drazzibdrazzibpackage example.xml; import java.util.Collections; public class SimCard implements Contacts { public Iterable findByName(String name) { return Collections.emptyList(); } }guice-3.0/examples/src/example/xml/Main.java0000644000175000017500000000247411254111602020733 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package example.xml; import com.google.inject.Guice; import com.google.inject.AbstractModule; import com.google.inject.Injector; import java.net.URL; /** * * */ public class Main { public static void main(String[] args) { final URL xmlUrl = Main.class.getResource("phone.xml"); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Contacts.class).to(SimCard.class); install(new XmlBeanModule(xmlUrl)); } }); Phone phone = injector.getInstance(Phone.class); if (phone.getContacts() == null) { throw new AssertionError(); } else { System.out.println("It worked!"); } } } guice-3.0/core/0000755000175000017500000000000011542721074013277 5ustar drazzibdrazzibguice-3.0/core/pom.xml0000644000175000017500000001655311510705016014617 0ustar drazzibdrazzib 4.0.0 com.google.inject guice-parent 3.0-SNAPSHOT guice Google Guice - Core Library 2.2.1-v20090111 javax.inject javax.inject 1 aopalliance aopalliance 1.0 org.sonatype.sisu.inject cglib ${cglib.version} javax.inject javax.inject-tck 1 test org.springframework spring-beans 3.0.5.RELEASE test biz.aQute bnd 0.0.384 test org.apache.felix org.apache.felix.framework 3.0.5 test maven-remote-resources-plugin org.codehaus.mojo animal-sniffer-maven-plugin maven-surefire-plugin **/OSGiContainerTest* **/ScopesTest* **/TypeConversionTest* org.apache.felix maven-bundle-plugin maven-jar-plugin LICENSE NOTICE guice.with.no_aop guice.with.no_aop !false org.sonatype.plugins munge-maven-plugin 1.0 prepare-package munge-fork NO_AOP **/InterceptorBinding.java, **/InterceptorBindingProcessor.java, **/InterceptorStackCallback.java, **/LineNumbers.java, **/MethodAspect.java, **/ProxyFactory.java, **/BytecodeGenTest.java, **/IntegrationTest.java, **/MethodInterceptionTest.java, **/ProxyFactoryTest.java maven-jar-plugin no_aop package jar ${project.build.directory}/munged/classes no_aop ${project.build.directory}/munged/classes/META-INF/MANIFEST.MF guice.with.jarjar guice.with.jarjar !false org.sonatype.sisu.inject cglib ${cglib.version} true org.sonatype.plugins jarjar-maven-plugin *:asm *:cglib maven-jar-plugin no_deps package jar ${project.build.directory}/original-classes no_deps guice-3.0/core/test/0000755000175000017500000000000011460132764014257 5ustar drazzibdrazzibguice-3.0/core/test/com/0000755000175000017500000000000011460132764015035 5ustar drazzibdrazzibguice-3.0/core/test/com/google/0000755000175000017500000000000011460132764016311 5ustar drazzibdrazzibguice-3.0/core/test/com/google/inject/0000755000175000017500000000000011536225574017573 5ustar drazzibdrazzibguice-3.0/core/test/com/google/inject/ScopesTest.java0000644000175000017500000005031511461076546022536 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.Maps; import com.google.inject.name.Named; import static com.google.inject.name.Names.named; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; import com.google.inject.spi.PrivateElements; import com.google.inject.util.Providers; import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class ScopesTest extends TestCase { private final AbstractModule singletonsModule = new AbstractModule() { protected void configure() { bind(BoundAsSingleton.class).in(Scopes.SINGLETON); bind(AnnotatedSingleton.class); bind(EagerSingleton.class).asEagerSingleton(); bind(LinkedSingleton.class).to(RealLinkedSingleton.class); bind(DependsOnJustInTimeSingleton.class); bind(NotASingleton.class); bind(ImplementedBySingleton.class).in(Scopes.SINGLETON); bind(ProvidedBySingleton.class).in(Scopes.SINGLETON); } }; @Override protected void setUp() throws Exception { AnnotatedSingleton.nextInstanceId = 0; BoundAsSingleton.nextInstanceId = 0; EagerSingleton.nextInstanceId = 0; RealLinkedSingleton.nextInstanceId = 0; JustInTimeSingleton.nextInstanceId = 0; NotASingleton.nextInstanceId = 0; Implementation.nextInstanceId = 0; ProvidedBySingleton.nextInstanceId = 0; ThrowingSingleton.nextInstanceId = 0; } public void testSingletons() { Injector injector = Guice.createInjector(singletonsModule); assertSame( injector.getInstance(BoundAsSingleton.class), injector.getInstance(BoundAsSingleton.class)); assertSame( injector.getInstance(AnnotatedSingleton.class), injector.getInstance(AnnotatedSingleton.class)); assertSame( injector.getInstance(EagerSingleton.class), injector.getInstance(EagerSingleton.class)); assertSame( injector.getInstance(LinkedSingleton.class), injector.getInstance(LinkedSingleton.class)); assertSame( injector.getInstance(JustInTimeSingleton.class), injector.getInstance(JustInTimeSingleton.class)); assertNotSame( injector.getInstance(NotASingleton.class), injector.getInstance(NotASingleton.class)); assertSame( injector.getInstance(ImplementedBySingleton.class), injector.getInstance(ImplementedBySingleton.class)); assertSame( injector.getInstance(ProvidedBySingleton.class), injector.getInstance(ProvidedBySingleton.class)); } public void testJustInTimeAnnotatedSingleton() { Injector injector = Guice.createInjector(); assertSame( injector.getInstance(AnnotatedSingleton.class), injector.getInstance(AnnotatedSingleton.class)); } public void testSingletonIsPerInjector() { assertNotSame( Guice.createInjector().getInstance(AnnotatedSingleton.class), Guice.createInjector().getInstance(AnnotatedSingleton.class)); } public void testOverriddingAnnotation() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(AnnotatedSingleton.class).in(Scopes.NO_SCOPE); } }); assertNotSame( injector.getInstance(AnnotatedSingleton.class), injector.getInstance(AnnotatedSingleton.class)); } public void testScopingAnnotationsOnAbstractTypeViaBind() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(A.class).to(AImpl.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), A.class.getName() + " is annotated with " + Singleton.class.getName(), "but scope annotations are not supported for abstract types.", "at " + A.class.getName() + ".class(ScopesTest.java:"); } } @Singleton interface A {} static class AImpl implements A {} public void testScopingAnnotationsOnAbstractTypeViaImplementedBy() { try { Guice.createInjector().getInstance(D.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), D.class.getName() + " is annotated with " + Singleton.class.getName(), "but scope annotations are not supported for abstract types.", "at " + D.class.getName() + ".class(ScopesTest.java:"); } } @Singleton @ImplementedBy(DImpl.class) interface D {} static class DImpl implements D {} public void testScopingAnnotationsOnAbstractTypeViaProvidedBy() { try { Guice.createInjector().getInstance(E.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), E.class.getName() + " is annotated with " + Singleton.class.getName(), "but scope annotations are not supported for abstract types.", "at " + E.class.getName() + ".class(ScopesTest.java:"); } } @Singleton @ProvidedBy(EProvider.class) interface E {} static class EProvider implements Provider { public E get() { return null; } } public void testScopeUsedButNotBound() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(B.class).in(CustomScoped.class); bind(C.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) No scope is bound to " + CustomScoped.class.getName(), "at " + getClass().getName(), ".configure(ScopesTest.java:", "2) No scope is bound to " + CustomScoped.class.getName(), "at " + C.class.getName() + ".class"); } } static class B {} @CustomScoped static class C {} public void testSingletonsInProductionStage() { Guice.createInjector(Stage.PRODUCTION, singletonsModule); assertEquals(1, AnnotatedSingleton.nextInstanceId); assertEquals(1, BoundAsSingleton.nextInstanceId); assertEquals(1, EagerSingleton.nextInstanceId); assertEquals(1, RealLinkedSingleton.nextInstanceId); assertEquals(1, JustInTimeSingleton.nextInstanceId); assertEquals(0, NotASingleton.nextInstanceId); } public void testSingletonsInDevelopmentStage() { Guice.createInjector(Stage.DEVELOPMENT, singletonsModule); assertEquals(0, AnnotatedSingleton.nextInstanceId); assertEquals(0, BoundAsSingleton.nextInstanceId); assertEquals(1, EagerSingleton.nextInstanceId); assertEquals(0, RealLinkedSingleton.nextInstanceId); assertEquals(0, JustInTimeSingleton.nextInstanceId); assertEquals(0, NotASingleton.nextInstanceId); } public void testSingletonScopeIsNotSerializable() throws IOException { Asserts.assertNotSerializable(Scopes.SINGLETON); } public void testNoScopeIsNotSerializable() throws IOException { Asserts.assertNotSerializable(Scopes.NO_SCOPE); } public void testUnscopedProviderWorksOutsideOfRequestedScope() { final RememberProviderScope scope = new RememberProviderScope(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindScope(CustomScoped.class, scope); bind(List.class).to(ArrayList.class).in(CustomScoped.class); } }); injector.getInstance(List.class); Provider listProvider = scope.providers.get(Key.get(List.class)); // this line fails with a NullPointerException because the Providers // passed to Scope.scope() don't work outside of the scope() method. assertTrue(listProvider.get() instanceof ArrayList); } public void testScopeAnnotationWithoutRuntimeRetention() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bindScope(NotRuntimeRetainedScoped.class, Scopes.NO_SCOPE); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Please annotate with @Retention(RUNTIME).", "at " + NotRuntimeRetainedScoped.class.getName() + ".class(ScopesTest.java:"); } } public void testBindScopeToAnnotationWithoutScopeAnnotation() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bindScope(Deprecated.class, Scopes.NO_SCOPE); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Please annotate with @ScopeAnnotation.", "at " + Deprecated.class.getName() + ".class("); } } public void testBindScopeTooManyTimes() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bindScope(CustomScoped.class, Scopes.NO_SCOPE); bindScope(CustomScoped.class, Scopes.SINGLETON); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Scope Scopes.NO_SCOPE is already bound to " + CustomScoped.class.getName(), "Cannot bind Scopes.SINGLETON.", "at " + ScopesTest.class.getName(), ".configure(ScopesTest.java:"); } } public void testDuplicateScopeAnnotations() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindScope(CustomScoped.class, Scopes.NO_SCOPE); } }); try { injector.getInstance(SingletonAndCustomScoped.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "1) More than one scope annotation was found: ", "while locating " + SingletonAndCustomScoped.class.getName()); } } public void testNullScopedAsASingleton() { Provider unscoped = new Provider() { final Iterator values = Arrays.asList(null, "A").iterator(); public String get() { return values.next(); } }; Provider scoped = Scopes.SINGLETON.scope(Key.get(String.class), unscoped); assertNull(scoped.get()); assertNull(scoped.get()); assertNull(scoped.get()); } class RememberProviderScope implements Scope { final Map, Provider> providers = Maps.newHashMap(); public Provider scope(Key key, Provider unscoped) { providers.put(key, unscoped); return unscoped; } } public void testSingletonAnnotationOnParameterizedType() { Injector injector = Guice.createInjector(); assertSame(injector.getInstance(new Key>() {}), injector.getInstance(new Key>() {})); assertSame(injector.getInstance(new Key>() {}), injector.getInstance(new Key>() {})); } @ImplementedBy(Injected.class) public interface In {} @Singleton public static class Injected implements In {} @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RUNTIME) @ScopeAnnotation public @interface CustomScoped {} @Target({ ElementType.TYPE, ElementType.METHOD }) @ScopeAnnotation public @interface NotRuntimeRetainedScoped {} @Singleton static class AnnotatedSingleton { static int nextInstanceId; final int instanceId = nextInstanceId++; } static class BoundAsSingleton { static int nextInstanceId; final int instanceId = nextInstanceId++; } static class EagerSingleton { static int nextInstanceId; final int instanceId = nextInstanceId++; } interface LinkedSingleton {} @Singleton static class RealLinkedSingleton implements LinkedSingleton { static int nextInstanceId; final int instanceId = nextInstanceId++; } static class DependsOnJustInTimeSingleton { @Inject JustInTimeSingleton justInTimeSingleton; } @Singleton static class JustInTimeSingleton { static int nextInstanceId; final int instanceId = nextInstanceId++; } static class NotASingleton { static int nextInstanceId; final int instanceId = nextInstanceId++; } @Singleton @CustomScoped static class SingletonAndCustomScoped {} @ImplementedBy(Implementation.class) static interface ImplementedBySingleton {} @ProvidedBy(ImplementationProvider.class) static class ProvidedBySingleton { static int nextInstanceId; final int instanceId = nextInstanceId++; } static class Implementation implements ImplementedBySingleton { static int nextInstanceId; final int instanceId = nextInstanceId++; } static class ImplementationProvider implements Provider { public ProvidedBySingleton get() { return new ProvidedBySingleton(); } } public void testScopeThatGetsAnUnrelatedObject() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(B.class); bind(C.class); ProviderGetScope providerGetScope = new ProviderGetScope(); requestInjection(providerGetScope); bindScope(CustomScoped.class, providerGetScope); } }); injector.getInstance(C.class); } class ProviderGetScope implements Scope { @Inject Provider bProvider; public Provider scope(Key key, final Provider unscoped) { return new Provider() { public T get() { bProvider.get(); return unscoped.get(); } }; } } public void testIsSingletonPositive() { final Key a = Key.get(String.class, named("A")); final Key b = Key.get(String.class, named("B")); final Key c = Key.get(String.class, named("C")); final Key d = Key.get(String.class, named("D")); final Key e = Key.get(String.class, named("E")); final Key f = Key.get(String.class, named("F")); final Key g = Key.get(String.class, named("G")); final Key h = Key.get(Object.class, named("H")); final Key i = Key.get(String.class, named("I")); Module singletonBindings = new AbstractModule() { protected void configure() { bind(a).to(b); bind(b).to(c); bind(c).toProvider(Providers.of("c")).in(Scopes.SINGLETON); bind(d).toInstance("d"); bind(e).toProvider(Providers.of("e")).asEagerSingleton(); bind(f).toProvider(Providers.of("f")).in(Singleton.class); bind(h).to(AnnotatedSingleton.class); install(new PrivateModule() { @Override protected void configure() { bind(i).toProvider(Providers.of("i")).in(Singleton.class); expose(i); } }); } @Provides @Named("G") @Singleton String provideG() { return "g"; } }; @SuppressWarnings("unchecked") // we know the module contains only bindings List moduleBindings = Elements.getElements(singletonBindings); ImmutableMap, Binding> map = indexBindings(moduleBindings); assertFalse(Scopes.isSingleton(map.get(a))); // linked bindings are not followed by modules assertFalse(Scopes.isSingleton(map.get(b))); assertTrue(Scopes.isSingleton(map.get(c))); assertTrue(Scopes.isSingleton(map.get(d))); assertTrue(Scopes.isSingleton(map.get(e))); assertTrue(Scopes.isSingleton(map.get(f))); assertTrue(Scopes.isSingleton(map.get(g))); assertFalse(Scopes.isSingleton(map.get(h))); // annotated classes are not followed by modules assertTrue(Scopes.isSingleton(map.get(i))); Injector injector = Guice.createInjector(singletonBindings); assertTrue(Scopes.isSingleton(injector.getBinding(a))); assertTrue(Scopes.isSingleton(injector.getBinding(b))); assertTrue(Scopes.isSingleton(injector.getBinding(c))); assertTrue(Scopes.isSingleton(injector.getBinding(d))); assertTrue(Scopes.isSingleton(injector.getBinding(e))); assertTrue(Scopes.isSingleton(injector.getBinding(f))); assertTrue(Scopes.isSingleton(injector.getBinding(g))); assertTrue(Scopes.isSingleton(injector.getBinding(h))); assertTrue(Scopes.isSingleton(injector.getBinding(i))); } public void testIsSingletonNegative() { final Key a = Key.get(String.class, named("A")); final Key b = Key.get(String.class, named("B")); final Key c = Key.get(String.class, named("C")); final Key d = Key.get(String.class, named("D")); final Key e = Key.get(String.class, named("E")); final Key f = Key.get(String.class, named("F")); Module singletonBindings = new AbstractModule() { protected void configure() { bind(a).to(b); bind(b).to(c); bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE); bind(d).toProvider(Providers.of("d")).in(CustomScoped.class); bindScope(CustomScoped.class, Scopes.NO_SCOPE); install(new PrivateModule() { @Override protected void configure() { bind(f).toProvider(Providers.of("f")).in(CustomScoped.class); expose(f); } }); } @Provides @Named("E") @CustomScoped String provideE() { return "e"; } }; @SuppressWarnings("unchecked") // we know the module contains only bindings List moduleBindings = Elements.getElements(singletonBindings); ImmutableMap, Binding> map = indexBindings(moduleBindings); assertFalse(Scopes.isSingleton(map.get(a))); assertFalse(Scopes.isSingleton(map.get(b))); assertFalse(Scopes.isSingleton(map.get(c))); assertFalse(Scopes.isSingleton(map.get(d))); assertFalse(Scopes.isSingleton(map.get(e))); assertFalse(Scopes.isSingleton(map.get(f))); Injector injector = Guice.createInjector(singletonBindings); assertFalse(Scopes.isSingleton(injector.getBinding(a))); assertFalse(Scopes.isSingleton(injector.getBinding(b))); assertFalse(Scopes.isSingleton(injector.getBinding(c))); assertFalse(Scopes.isSingleton(injector.getBinding(d))); assertFalse(Scopes.isSingleton(injector.getBinding(e))); assertFalse(Scopes.isSingleton(injector.getBinding(f))); } ImmutableMap, Binding> indexBindings(Iterable elements) { ImmutableMap.Builder, Binding> builder = ImmutableMap.builder(); for (Element element : elements) { if (element instanceof Binding) { Binding binding = (Binding) element; builder.put(binding.getKey(), binding); } else if (element instanceof PrivateElements) { PrivateElements privateElements = (PrivateElements)element; Map, Binding> privateBindings = indexBindings(privateElements.getElements()); for(Key exposed : privateElements.getExposedKeys()) { builder.put(exposed, privateBindings.get(exposed)); } } } return builder.build(); } @Singleton static class ThrowingSingleton { static int nextInstanceId; final int instanceId = nextInstanceId++; ThrowingSingleton() { if (instanceId == 0) { throw new RuntimeException(); } } } public void testSingletonConstructorThrows() { Injector injector = Guice.createInjector(); try { injector.getInstance(ThrowingSingleton.class); fail(); } catch (ProvisionException expected) { } // this behaviour is unspecified. If we change Guice to re-throw the exception, this test // should be changed injector.getInstance(ThrowingSingleton.class); assertEquals(2, ThrowingSingleton.nextInstanceId); } } guice-3.0/core/test/com/google/inject/TypeListenerTest.java0000644000175000017500000005232511530010440023706 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Lists; import com.google.inject.matcher.Matcher; import com.google.inject.matcher.Matchers; import static com.google.inject.matcher.Matchers.any; import static com.google.inject.matcher.Matchers.only; import static com.google.inject.name.Names.named; import com.google.inject.spi.InjectionListener; import com.google.inject.spi.Message; import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeListener; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class TypeListenerTest extends TestCase { private final Matcher onlyAbcd = Matchers.only(new TypeLiteral() {}) .or(only(new TypeLiteral() {})) .or(only(new TypeLiteral() {})) .or(only(new TypeLiteral() {})); final TypeListener failingTypeListener = new TypeListener() { int failures = 0; public void hear(TypeLiteral type, TypeEncounter encounter) { throw new ClassCastException("whoops, failure #" + (++failures)); } @Override public String toString() { return "clumsy"; } }; final InjectionListener failingInjectionListener = new InjectionListener() { int failures = 0; public void afterInjection(Object injectee) { throw new ClassCastException("whoops, failure #" + (++failures)); } @Override public String toString() { return "goofy"; } }; final MembersInjector failingMembersInjector = new MembersInjector() { int failures = 0; public void injectMembers(Object instance) { throw new ClassCastException("whoops, failure #" + (++failures)); } @Override public String toString() { return "awkward"; } }; public void testTypeListenersAreFired() throws NoSuchMethodException { final AtomicInteger firedCount = new AtomicInteger(); final TypeListener typeListener = new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { assertEquals(new TypeLiteral() {}, type); firedCount.incrementAndGet(); } }; Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(onlyAbcd, typeListener); bind(A.class); } }); assertEquals(1, firedCount.get()); } public void testInstallingInjectionListener() { final List injectees = Lists.newArrayList(); final InjectionListener injectionListener = new InjectionListener() { public void afterInjection(Object injectee) { injectees.add(injectee); } }; Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(onlyAbcd, new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { encounter.register(injectionListener); } }); bind(A.class); } }); assertEquals(ImmutableList.of(), injectees); Object a1 = injector.getInstance(A.class); assertEquals(ImmutableList.of(a1), injectees); Object a2 = injector.getInstance(A.class); assertEquals(ImmutableList.of(a1, a2), injectees); Object b1 = injector.getInstance(B.class); assertEquals(ImmutableList.of(a1, a2, b1), injectees); Provider aProvider = injector.getProvider(A.class); assertEquals(ImmutableList.of(a1, a2, b1), injectees); A a3 = aProvider.get(); A a4 = aProvider.get(); assertEquals(ImmutableList.of(a1, a2, b1, a3, a4), injectees); } /*if[AOP]*/ private static org.aopalliance.intercept.MethodInterceptor prefixInterceptor( final String prefix) { return new org.aopalliance.intercept.MethodInterceptor() { public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) throws Throwable { return prefix + methodInvocation.proceed(); } }; } public void testAddingInterceptors() throws NoSuchMethodException { final Matcher buzz = only(C.class.getMethod("buzz")); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindInterceptor(any(), buzz, prefixInterceptor("ka")); bindInterceptor(any(), any(), prefixInterceptor("fe")); bindListener(onlyAbcd, new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { encounter.bindInterceptor(any(), prefixInterceptor("li")); encounter.bindInterceptor(buzz, prefixInterceptor("no")); } }); } }); // interceptors must be invoked in the order they're bound. C c = injector.getInstance(C.class); assertEquals("kafelinobuzz", c.buzz()); assertEquals("felibeep", c.beep()); } /*end[AOP]*/ public void testTypeListenerThrows() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(onlyAbcd, failingTypeListener); bind(B.class); bind(C.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Error notifying TypeListener clumsy (bound at " + getClass().getName(), ".configure(TypeListenerTest.java:", "of " + B.class.getName(), "Reason: java.lang.ClassCastException: whoops, failure #1", "2) Error notifying TypeListener clumsy (bound at " + getClass().getName(), ".configure(TypeListenerTest.java:", "of " + C.class.getName(), "Reason: java.lang.ClassCastException: whoops, failure #2"); } Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(onlyAbcd, failingTypeListener); } }); try { injector.getProvider(B.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "1) Error notifying TypeListener clumsy (bound at " + getClass().getName(), ".configure(TypeListenerTest.java:", "of " + B.class.getName(), "Reason: java.lang.ClassCastException: whoops, failure #3"); } // getting it again should yield the same exception #3 try { injector.getInstance(B.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "1) Error notifying TypeListener clumsy (bound at " + getClass().getName(), ".configure(TypeListenerTest.java:", "of " + B.class.getName(), "Reason: java.lang.ClassCastException: whoops, failure #3"); } // non-injected types do not participate assertSame(Stage.DEVELOPMENT, injector.getInstance(Stage.class)); } public void testInjectionListenerThrows() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(onlyAbcd, new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { encounter.register(failingInjectionListener); } }); bind(B.class); } }); try { injector.getInstance(A.class); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "1) Error notifying InjectionListener goofy of " + A.class.getName(), " Reason: java.lang.ClassCastException: whoops, failure #1"); } // second time through should be a new cause (#2) try { injector.getInstance(A.class); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "1) Error notifying InjectionListener goofy of " + A.class.getName(), " Reason: java.lang.ClassCastException: whoops, failure #2"); } // we should get errors for all types, but only on getInstance() Provider bProvider = injector.getProvider(B.class); try { bProvider.get(); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "1) Error notifying InjectionListener goofy of " + B.class.getName(), " Reason: java.lang.ClassCastException: whoops, failure #3"); } // non-injected types do not participate assertSame(Stage.DEVELOPMENT, injector.getInstance(Stage.class)); } public void testInjectMembersTypeListenerFails() { try { Guice.createInjector(new AbstractModule() { protected void configure() { getMembersInjector(A.class); bindListener(onlyAbcd, failingTypeListener); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Error notifying TypeListener clumsy (bound at ", TypeListenerTest.class.getName(), ".configure(TypeListenerTest.java:", "of " + A.class.getName(), " Reason: java.lang.ClassCastException: whoops, failure #1"); } } public void testConstructedTypeListenerIsTheSameAsMembersInjectorListener() { final AtomicInteger typeEncounters = new AtomicInteger(); final AtomicInteger injections = new AtomicInteger(); final InjectionListener listener = new InjectionListener() { public void afterInjection(A injectee) { injections.incrementAndGet(); assertNotNull(injectee.injector); } }; Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(onlyAbcd, new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { typeEncounters.incrementAndGet(); encounter.register((InjectionListener) listener); } }); bind(A.class); getMembersInjector(A.class); } }); // creating the injector shouldn't trigger injections assertEquals(0, injections.getAndSet(0)); // constructing an A should trigger an injection injector.getInstance(A.class); assertEquals(1, injections.getAndSet(0)); // injecting an A should trigger an injection injector.injectMembers(new A()); assertEquals(1, injections.getAndSet(0)); // getting a provider shouldn't Provider aProvider = injector.getProvider(A.class); MembersInjector aMembersInjector = injector.getMembersInjector(A.class); assertEquals(0, injections.getAndSet(0)); // exercise the provider aProvider.get(); aProvider.get(); assertEquals(2, injections.getAndSet(0)); // exercise the members injector aMembersInjector.injectMembers(new A()); aMembersInjector.injectMembers(new A()); assertEquals(2, injections.getAndSet(0)); // we should only have encountered one type assertEquals(1, typeEncounters.getAndSet(0)); } public void testLookupsAtInjectorCreateTime() { final AtomicReference> bProviderReference = new AtomicReference>(); final AtomicReference> aMembersInjectorReference = new AtomicReference>(); final InjectionListener lookupsTester = new InjectionListener() { public void afterInjection(Object injectee) { assertNotNull(bProviderReference.get().get()); A a = new A(); aMembersInjectorReference.get().injectMembers(a); assertNotNull(a.injector); } }; Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(only(TypeLiteral.get(C.class)), new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { Provider bProvider = encounter.getProvider(B.class); try { bProvider.get(); fail(); } catch (IllegalStateException expected) { assertEquals("This Provider cannot be used until the Injector has been created.", expected.getMessage()); } bProviderReference.set(bProvider); MembersInjector aMembersInjector = encounter.getMembersInjector(A.class); try { aMembersInjector.injectMembers(new A()); fail(); } catch (IllegalStateException expected) { assertEquals( "This MembersInjector cannot be used until the Injector has been created.", expected.getMessage()); } aMembersInjectorReference.set(aMembersInjector); encounter.register(lookupsTester); } }); // this ensures the type listener fires, and also the afterInjection() listener bind(C.class).asEagerSingleton(); } }); lookupsTester.afterInjection(null); } public void testLookupsPostCreate() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(only(TypeLiteral.get(C.class)), new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { assertNotNull(encounter.getProvider(B.class).get()); A a = new A(); encounter.getMembersInjector(A.class).injectMembers(a); assertNotNull(a.injector); } }); } }); injector.getInstance(C.class); } public void testMembersInjector() { final MembersInjector membersInjector = new MembersInjector() { public void injectMembers(D instance) { instance.userInjected++; assertEquals(instance.guiceInjected, instance.userInjected); } }; final InjectionListener injectionListener = new InjectionListener() { public void afterInjection(D injectee) { assertTrue(injectee.userInjected > 0); injectee.listenersNotified++; assertEquals(injectee.guiceInjected, injectee.listenersNotified); } }; Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(onlyAbcd, new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { encounter.register((MembersInjector) membersInjector); encounter.register((InjectionListener) injectionListener); } }); D boundThreeTimes = new D(); bind(D.class).annotatedWith(named("i")).toInstance(boundThreeTimes); bind(D.class).annotatedWith(named("ii")).toInstance(boundThreeTimes); bind(D.class).annotatedWith(named("iii")).toInstance(boundThreeTimes); } }); D boundThreeTimes = injector.getInstance(Key.get(D.class, named("iii"))); boundThreeTimes.assertAllCounts(1); D getInstance = injector.getInstance(D.class); getInstance.assertAllCounts(1); D memberInjection = new D(); injector.injectMembers(memberInjection); memberInjection.assertAllCounts(1); injector.injectMembers(memberInjection); injector.injectMembers(memberInjection); memberInjection.assertAllCounts(3); injector.getMembersInjector(D.class).injectMembers(memberInjection); memberInjection.assertAllCounts(4); } public void testMembersInjectorThrows() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(onlyAbcd, new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { encounter.register(failingMembersInjector); } }); bind(B.class); } }); try { injector.getInstance(A.class); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "1) Error injecting " + A.class.getName() + " using awkward.", "Reason: java.lang.ClassCastException: whoops, failure #1"); } // second time through should be a new cause (#2) try { injector.getInstance(A.class); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "1) Error injecting " + A.class.getName() + " using awkward.", "Reason: java.lang.ClassCastException: whoops, failure #2"); } // we should get errors for all types, but only on getInstance() Provider bProvider = injector.getProvider(B.class); try { bProvider.get(); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "1) Error injecting " + B.class.getName() + " using awkward.", "Reason: java.lang.ClassCastException: whoops, failure #3"); } // non-injected types do not participate assertSame(Stage.DEVELOPMENT, injector.getInstance(Stage.class)); } /** * We had a bug where we weren't notifying of types encountered for member injection when those * types had no members to be injected. Constructed types are always injected because they always * have at least one injection point: the class constructor. */ public void testTypesWithNoInjectableMembersAreNotified() { final AtomicInteger notificationCount = new AtomicInteger(); Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(onlyAbcd, new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { notificationCount.incrementAndGet(); } }); bind(C.class).toInstance(new C()); } }); assertEquals(1, notificationCount.get()); } public void testEncounterCannotBeUsedAfterHearReturns() { final AtomicReference> encounterReference = new AtomicReference>(); Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(any(), new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { encounterReference.set(encounter); } }); bind(C.class); } }); TypeEncounter encounter = encounterReference.get(); try { encounter.register(new InjectionListener() { public void afterInjection(Object injectee) {} }); fail(); } catch (IllegalStateException expected) { } /*if[AOP]*/ try { encounter.bindInterceptor(any(), new org.aopalliance.intercept.MethodInterceptor() { public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) throws Throwable { return methodInvocation.proceed(); } }); fail(); } catch (IllegalStateException expected) { } /*end[AOP]*/ try { encounter.addError(new Exception()); fail(); } catch (IllegalStateException expected) { } try { encounter.getMembersInjector(A.class); fail(); } catch (IllegalStateException expected) { } try { encounter.getProvider(B.class); fail(); } catch (IllegalStateException expected) { } } public void testAddErrors() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bindListener(Matchers.only(new TypeLiteral() {}), new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { encounter.addError("There was an error on %s", type); encounter.addError(new IllegalArgumentException("whoops!")); encounter.addError(new Message("And another problem")); encounter.addError(new IllegalStateException()); } }); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) There was an error on com.google.inject.Stage", "2) An exception was caught and reported. Message: whoops!", "3) And another problem", "4) An exception was caught and reported. Message: null", "4 errors"); } } // TODO: recursively accessing a lookup should fail static class A { @Inject Injector injector; @Inject Stage stage; } static class B {} public static class C { public String buzz() { return "buzz"; } public String beep() { return "beep"; } } static class D { int guiceInjected = 0; int userInjected = 0; int listenersNotified = 0; @Inject void guiceInjected() { guiceInjected++; } void assertAllCounts(int expected) { assertEquals(expected, guiceInjected); assertEquals(expected, userInjected); assertEquals(expected, listenersNotified); } } } guice-3.0/core/test/com/google/inject/OverrideModuleTest.java0000644000175000017500000004704711464100204024215 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import static com.google.inject.Guice.createInjector; import static com.google.inject.name.Names.named; import com.google.inject.internal.util.Objects; import com.google.inject.name.Named; import com.google.inject.util.Modules; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import java.util.Date; import java.util.concurrent.atomic.AtomicReference; import junit.framework.TestCase; /** * @author sberlin@gmail.com (Sam Berlin) */ public class OverrideModuleTest extends TestCase { private static final Key key2 = Key.get(String.class, named("2")); private static final Key key3 = Key.get(String.class, named("3")); private static final Module EMPTY_MODULE = new Module() { public void configure(Binder binder) {} }; public void testOverride() { Injector injector = createInjector(Modules.override(newModule("A")).with(newModule("B"))); assertEquals("B", injector.getInstance(String.class)); } public void testOverrideMultiple() { Module module = Modules.override(newModule("A"), newModule(1), newModule(0.5f)) .with(newModule("B"), newModule(2), newModule(1.5d)); Injector injector = createInjector(module); assertEquals("B", injector.getInstance(String.class)); assertEquals(2, injector.getInstance(Integer.class).intValue()); assertEquals(0.5f, injector.getInstance(Float.class)); assertEquals(1.5d, injector.getInstance(Double.class)); } public void testOverrideUnmatchedTolerated() { Injector injector = createInjector(Modules.override(EMPTY_MODULE).with(newModule("B"))); assertEquals("B", injector.getInstance(String.class)); } public void testOverrideConstant() { Module original = new AbstractModule() { @Override protected void configure() { bindConstant().annotatedWith(named("Test")).to("A"); } }; Module replacements = new AbstractModule() { @Override protected void configure() { bindConstant().annotatedWith(named("Test")).to("B"); } }; Injector injector = createInjector(Modules.override(original).with(replacements)); assertEquals("B", injector.getInstance(Key.get(String.class, named("Test")))); } public void testGetProviderInModule() { Module original = new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("A"); bind(key2).toProvider(getProvider(String.class)); } }; Injector injector = createInjector(Modules.override(original).with(EMPTY_MODULE)); assertEquals("A", injector.getInstance(String.class)); assertEquals("A", injector.getInstance(key2)); } public void testOverrideWhatGetProviderProvided() { Module original = new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("A"); bind(key2).toProvider(getProvider(String.class)); } }; Module replacements = newModule("B"); Injector injector = createInjector(Modules.override(original).with(replacements)); assertEquals("B", injector.getInstance(String.class)); assertEquals("B", injector.getInstance(key2)); } public void testOverrideUsingOriginalsGetProvider() { Module original = new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("A"); bind(key2).toInstance("B"); } }; Module replacements = new AbstractModule() { @Override protected void configure() { bind(String.class).toProvider(getProvider(key2)); } }; Injector injector = createInjector(Modules.override(original).with(replacements)); assertEquals("B", injector.getInstance(String.class)); assertEquals("B", injector.getInstance(key2)); } public void testOverrideOfOverride() { Module original = new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("A1"); bind(key2).toInstance("A2"); bind(key3).toInstance("A3"); } }; Module replacements1 = new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("B1"); bind(key2).toInstance("B2"); } }; Module overrides = Modules.override(original).with(replacements1); Module replacements2 = new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("C1"); bind(key3).toInstance("C3"); } }; Injector injector = createInjector(Modules.override(overrides).with(replacements2)); assertEquals("C1", injector.getInstance(String.class)); assertEquals("B2", injector.getInstance(key2)); assertEquals("C3", injector.getInstance(key3)); } public void testOverridesTwiceFails() { Module original = newModule("A"); Module replacements = new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("B"); bind(String.class).toInstance("C"); } }; Module module = Modules.override(original).with(replacements); try { createInjector(module); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "A binding to java.lang.String " + "was already configured at " + replacements.getClass().getName(), "at " + replacements.getClass().getName()); } } public void testOverridesDoesntFixTwiceBoundInOriginal() { Module original = new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("A"); bind(String.class).toInstance("B"); } }; Module replacements = new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("C"); } }; Module module = Modules.override(original).with(replacements); try { createInjector(module); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) A binding to java.lang.String " + "was already configured at " + replacements.getClass().getName(), "at " + original.getClass().getName()); } } public void testStandardScopeAnnotation() { final SingleUseScope scope = new SingleUseScope(); Module module = new AbstractModule() { protected void configure() { bindScope(TestScopeAnnotation.class, scope); bind(String.class).in(TestScopeAnnotation.class); } }; assertFalse(scope.used); Guice.createInjector(module); assertTrue(scope.used); } public void testOverrideUntargettedBinding() { Module original = new AbstractModule() { @Override protected void configure() { bind(Date.class); } }; Module replacements = new AbstractModule() { @Override protected void configure() { bind(Date.class).toInstance(new Date(0)); } }; Injector injector = createInjector(Modules.override(original).with(replacements)); assertEquals(0, injector.getInstance(Date.class).getTime()); } public void testOverrideScopeAnnotation() { final Scope scope = new Scope() { public Provider scope(Key key, Provider unscoped) { throw new AssertionError("Should not be called"); } }; final SingleUseScope replacementScope = new SingleUseScope(); Module original = new AbstractModule() { @Override protected void configure() { bindScope(TestScopeAnnotation.class, scope); bind(Date.class).in(TestScopeAnnotation.class); } }; Module replacements = new AbstractModule() { @Override protected void configure() { bindScope(TestScopeAnnotation.class, replacementScope); } }; Injector injector = createInjector(Modules.override(original).with(replacements)); injector.getInstance(Date.class); assertTrue(replacementScope.used); } public void testFailsIfOverridenScopeInstanceHasBeenUsed() { final Scope scope = new Scope() { public Provider scope(Key key, Provider unscoped) { return unscoped; } @Override public String toString() { return "ORIGINAL SCOPE"; } }; Module original = new AbstractModule() { @Override protected void configure() { bindScope(TestScopeAnnotation.class, scope); bind(Date.class).in(scope); } }; Module replacements = new AbstractModule() { @Override protected void configure() { bindScope(TestScopeAnnotation.class, new SingleUseScope()); } }; try { createInjector(Modules.override(original).with(replacements)); fail("Exception expected"); } catch (CreationException e) { assertContains(e.getMessage(), "1) The scope for @TestScopeAnnotation is bound directly and cannot be overridden.", "at ", getClass().getName(), ".configure("); } } public void testOverrideIsLazy() { final AtomicReference value = new AtomicReference("A"); Module overridden = Modules.override(new AbstractModule() { protected void configure() { bind(String.class).annotatedWith(named("original")).toInstance(value.get()); } }).with(new AbstractModule() { protected void configure() { bind(String.class).annotatedWith(named("override")).toInstance(value.get()); } }); // the value.get() call should be deferred until Guice.createInjector value.set("B"); Injector injector = Guice.createInjector(overridden); assertEquals("B", injector.getInstance(Key.get(String.class, named("original")))); assertEquals("B", injector.getInstance(Key.get(String.class, named("override")))); } public void testOverridePrivateModuleOverPrivateModule() { Module exposes5and6 = new AbstractModule() { protected void configure() { install(new PrivateModule() { protected void configure() { bind(Integer.class).toInstance(5); expose(Integer.class); bind(Character.class).toInstance('E'); } }); install(new PrivateModule() { protected void configure() { bind(Long.class).toInstance(6L); expose(Long.class); bind(Character.class).toInstance('F'); } }); } }; AbstractModule exposes15 = new AbstractModule() { protected void configure() { install(new PrivateModule() { protected void configure() { bind(Integer.class).toInstance(15); expose(Integer.class); bind(Character.class).toInstance('G'); } }); install(new PrivateModule() { protected void configure() { bind(Character.class).toInstance('H'); } }); } }; // override forwards Injector injector = Guice.createInjector(Modules.override(exposes5and6).with(exposes15)); assertEquals(15, injector.getInstance(Integer.class).intValue()); assertEquals(6L, injector.getInstance(Long.class).longValue()); // and in reverse order Injector reverse = Guice.createInjector(Modules.override(exposes15).with(exposes5and6)); assertEquals(5, reverse.getInstance(Integer.class).intValue()); assertEquals(6L, reverse.getInstance(Long.class).longValue()); } public void testOverrideModuleAndPrivateModule() { Module exposes5 = new PrivateModule() { protected void configure() { bind(Integer.class).toInstance(5); expose(Integer.class); } }; Module binds15 = new AbstractModule() { protected void configure() { bind(Integer.class).toInstance(15); } }; Injector injector = Guice.createInjector(Modules.override(exposes5).with(binds15)); assertEquals(15, injector.getInstance(Integer.class).intValue()); Injector reverse = Guice.createInjector(Modules.override(binds15).with(exposes5)); assertEquals(5, reverse.getInstance(Integer.class).intValue()); } public void testOverrideDeepExpose() { final AtomicReference> charAProvider = new AtomicReference>(); Module exposes5 = new PrivateModule() { protected void configure() { install(new PrivateModule() { protected void configure() { bind(Integer.class).toInstance(5); expose(Integer.class); charAProvider.set(getProvider(Character.class)); bind(Character.class).toInstance('A'); } }); expose(Integer.class); } }; Injector injector = Guice.createInjector(Modules.override(exposes5).with(EMPTY_MODULE)); assertEquals(5, injector.getInstance(Integer.class).intValue()); assertEquals('A', charAProvider.getAndSet(null).get().charValue()); injector = Guice.createInjector(Modules.override(EMPTY_MODULE).with(exposes5)); assertEquals(5, injector.getInstance(Integer.class).intValue()); assertEquals('A', charAProvider.getAndSet(null).get().charValue()); final AtomicReference> charBProvider = new AtomicReference>(); Module binds15 = new AbstractModule() { protected void configure() { bind(Integer.class).toInstance(15); install(new PrivateModule() { protected void configure() { charBProvider.set(getProvider(Character.class)); bind(Character.class).toInstance('B'); } }); } }; injector = Guice.createInjector(Modules.override(binds15).with(exposes5)); assertEquals(5, injector.getInstance(Integer.class).intValue()); assertEquals('A', charAProvider.getAndSet(null).get().charValue()); assertEquals('B', charBProvider.getAndSet(null).get().charValue()); injector = Guice.createInjector(Modules.override(exposes5).with(binds15)); assertEquals(15, injector.getInstance(Integer.class).intValue()); assertEquals('A', charAProvider.getAndSet(null).get().charValue()); assertEquals('B', charBProvider.getAndSet(null).get().charValue()); } @Retention(RUNTIME) @Target(TYPE) @ScopeAnnotation private static @interface TestScopeAnnotation {} private static class SingleUseScope implements Scope { boolean used = false; public Provider scope(Key key, Provider unscoped) { assertFalse(used); used = true; return unscoped; } } private static Module newModule(final T bound) { return new AbstractModule() { @Override protected void configure() { @SuppressWarnings("unchecked") Class type = (Class) bound.getClass(); bind(type).toInstance(bound); } }; } private static final String RESULT = "RESULT"; private static final String PRIVATE_INPUT = "PRIVATE_INPUT"; private static final String OVERRIDDEN_INPUT = "FOO"; private static final String OVERRIDDEN_RESULT = "Size: 3"; private static final Key RESULT_KEY = Key.get(String.class, named(RESULT)); private static final Key INPUT_KEY = Key.get(String.class, named(PRIVATE_INPUT)); public void testExposedBindingOverride() throws Exception { Injector inj = Guice.createInjector( Modules.override(new ExampleModule()).with( new AbstractModule() { @Override protected void configure() { bind(RESULT_KEY).toInstance(OVERRIDDEN_RESULT); } })); assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT); } public void testPrivateBindingOverride() throws Exception { Injector inj = Guice.createInjector( Modules.override(new ExampleModule()).with( new AbstractModule() { @Override protected void configure() { bind(INPUT_KEY).toInstance(OVERRIDDEN_INPUT); } })); assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT); } public static class ExampleModule extends PrivateModule { @Provides @Exposed @Named(RESULT) public String provideResult(@Named(PRIVATE_INPUT) String input) { return "Size: " + input.length(); } @Provides @Named(PRIVATE_INPUT) public String provideInput() { return "Hello World"; } @Override protected void configure() { } } public void testEqualsNotCalledByDefaultOnInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnEquals = true; Guice.createInjector(Modules.override(new AbstractModule() { @Override protected void configure() { bind(String.class); bind(HashEqualsTester.class).toInstance(a); } }).with()); } public void testEqualsNotCalledByDefaultOnProvider() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnEquals = true; Guice.createInjector(Modules.override(new AbstractModule() { @Override protected void configure() { bind(String.class); bind(Object.class).toProvider(a); } }).with()); } public void testHashcodeNeverCalledOnInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnHashcode = true; a.equality = "test"; final HashEqualsTester b = new HashEqualsTester(); b.throwOnHashcode = true; b.equality = "test"; Guice.createInjector(Modules.override(new AbstractModule() { @Override protected void configure() { bind(String.class); bind(HashEqualsTester.class).toInstance(a); bind(HashEqualsTester.class).toInstance(b); } }).with()); } public void testHashcodeNeverCalledOnProviderInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnHashcode = true; a.equality = "test"; final HashEqualsTester b = new HashEqualsTester(); b.throwOnHashcode = true; b.equality = "test"; Guice.createInjector(Modules.override(new AbstractModule() { @Override protected void configure() { bind(String.class); bind(Object.class).toProvider(a); bind(Object.class).toProvider(b); } }).with()); } private static class HashEqualsTester implements Provider { private String equality; private boolean throwOnEquals; private boolean throwOnHashcode; @Override public boolean equals(Object obj) { if (throwOnEquals) { throw new RuntimeException(); } else if (obj instanceof HashEqualsTester) { HashEqualsTester o = (HashEqualsTester)obj; if(o.throwOnEquals) { throw new RuntimeException(); } if(equality == null && o.equality == null) { return this == o; } else { return Objects.equal(equality, o.equality); } } else { return false; } } @Override public int hashCode() { if(throwOnHashcode) { throw new RuntimeException(); } else { return super.hashCode(); } } public Object get() { return new Object(); } } } guice-3.0/core/test/com/google/inject/KeyTest.java0000644000175000017500000001732511460132772022027 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import static com.google.inject.Asserts.assertEqualsBothWays; import static com.google.inject.Asserts.assertNotSerializable; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.util.Types; import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.List; import java.util.Map; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class KeyTest extends TestCase { public void foo(List a, List b) {} public void bar(Provider> a) {} @Foo String baz; List wildcardExtends; public void testOfType() { Key k = Key.get(Object.class, Foo.class); Key ki = k.ofType(Integer.class); assertEquals(Integer.class, ki.getRawType()); assertEquals(Foo.class, ki.getAnnotationType()); } public void testKeyEquality() { Key> a = new Key>(Foo.class) {}; Key> b = Key.get(new TypeLiteral>() {}, Foo.class); assertEqualsBothWays(a, b); } public void testProviderKey() throws NoSuchMethodException { Key actual = Key.get(getClass().getMethod("foo", List.class, List.class) .getGenericParameterTypes()[0]).providerKey(); Key expected = Key.get(getClass().getMethod("bar", Provider.class) .getGenericParameterTypes()[0]); assertEqualsBothWays(expected, actual); assertEquals(expected.toString(), actual.toString()); } public void testTypeEquality() throws Exception { Method m = getClass().getMethod("foo", List.class, List.class); Type[] types = m.getGenericParameterTypes(); assertEquals(types[0], types[1]); Key> k = new Key>() {}; assertEquals(types[0], k.getTypeLiteral().getType()); assertFalse(types[0].equals( new Key>() {}.getTypeLiteral().getType())); } /** * Key canonicalizes {@link int.class} to {@code Integer.class}, and * won't expose wrapper types. */ public void testPrimitivesAndWrappersAreEqual() { Class[] primitives = new Class[] { boolean.class, byte.class, short.class, int.class, long.class, float.class, double.class, char.class, void.class }; Class[] wrappers = new Class[] { Boolean.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Character.class, Void.class }; for (int t = 0; t < primitives.length; t++) { @SuppressWarnings("unchecked") Key primitiveKey = Key.get(primitives[t]); @SuppressWarnings("unchecked") Key wrapperKey = Key.get(wrappers[t]); assertEquals(primitiveKey, wrapperKey); assertEquals(wrappers[t], primitiveKey.getRawType()); assertEquals(wrappers[t], wrapperKey.getRawType()); assertEquals(wrappers[t], primitiveKey.getTypeLiteral().getType()); assertEquals(wrappers[t], wrapperKey.getTypeLiteral().getType()); } Key integerKey = Key.get(Integer.class); Key integerKey2 = Key.get(Integer.class, Named.class); Key integerKey3 = Key.get(Integer.class, Names.named("int")); Class intClassLiteral = int.class; assertEquals(integerKey, Key.get(intClassLiteral)); assertEquals(integerKey2, Key.get(intClassLiteral, Named.class)); assertEquals(integerKey3, Key.get(intClassLiteral, Names.named("int"))); Type intType = int.class; assertEquals(integerKey, Key.get(intType)); assertEquals(integerKey2, Key.get(intType, Named.class)); assertEquals(integerKey3, Key.get(intType, Names.named("int"))); TypeLiteral intTypeLiteral = TypeLiteral.get(int.class); assertEquals(integerKey, Key.get(intTypeLiteral)); assertEquals(integerKey2, Key.get(intTypeLiteral, Named.class)); assertEquals(integerKey3, Key.get(intTypeLiteral, Names.named("int"))); } public void testSerialization() throws IOException, NoSuchFieldException { assertNotSerializable(Key.get(B.class)); assertNotSerializable(Key.get(B.class, Names.named("bee"))); assertNotSerializable(Key.get(B.class, Named.class)); assertNotSerializable(Key.get(B[].class)); assertNotSerializable(Key.get(new TypeLiteral, B>>() {})); assertNotSerializable(Key.get(new TypeLiteral>() {})); assertNotSerializable(Key.get(Types.listOf(Types.subtypeOf(CharSequence.class)))); } public void testEqualityOfAnnotationTypesAndInstances() throws NoSuchFieldException { Foo instance = getClass().getDeclaredField("baz").getAnnotation(Foo.class); Key keyWithInstance = Key.get(String.class, instance); Key keyWithLiteral = Key.get(String.class, Foo.class); assertEqualsBothWays(keyWithInstance, keyWithLiteral); } public void testNonBindingAnnotationOnKey() { try { Key.get(String.class, Deprecated.class); fail(); } catch (IllegalArgumentException expected) { assertContains(expected.getMessage(), "java.lang.Deprecated is not a binding annotation. ", "Please annotate it with @BindingAnnotation."); } } public void testBindingAnnotationWithoutRuntimeRetention() { try { Key.get(String.class, Bar.class); fail(); } catch (IllegalArgumentException expected) { assertContains(expected.getMessage(), Bar.class.getName() + " is not retained at runtime.", "Please annotate it with @Retention(RUNTIME)."); } } void parameterizedWithVariable(List typeWithVariables) {} /** Test for issue 186 */ public void testCannotCreateKeysWithTypeVariables() throws NoSuchMethodException { ParameterizedType listOfTType = (ParameterizedType) getClass().getDeclaredMethod( "parameterizedWithVariable", List.class).getGenericParameterTypes()[0]; TypeLiteral listOfT = TypeLiteral.get(listOfTType); try { Key.get(listOfT); fail("Guice should not allow keys for java.util.List"); } catch (ConfigurationException e) { assertContains(e.getMessage(), "java.util.List cannot be used as a key; It is not fully specified."); } TypeVariable tType = (TypeVariable) listOfTType.getActualTypeArguments()[0]; TypeLiteral t = TypeLiteral.get(tType); try { Key.get(t); fail("Guice should not allow keys for T"); } catch (ConfigurationException e) { assertContains(e.getMessage(), "T cannot be used as a key; It is not fully specified."); } } interface B {} @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation @interface Foo {} @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation @interface Bar {} class HasTypeParameters & Runnable, C extends Runnable> { A a; B b; C c; } } guice-3.0/core/test/com/google/inject/PrivateModuleTest.java0000644000175000017500000004566511532237456024074 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.name.Named; import com.google.inject.name.Names; import static com.google.inject.name.Names.named; import com.google.inject.spi.Dependency; import com.google.inject.spi.ExposedBinding; import com.google.inject.spi.PrivateElements; import com.google.inject.util.Types; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class PrivateModuleTest extends TestCase { public void testBasicUsage() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).annotatedWith(named("a")).toInstance("public"); install(new PrivateModule() { public void configure() { bind(String.class).annotatedWith(named("b")).toInstance("i"); bind(AB.class).annotatedWith(named("one")).to(AB.class); expose(AB.class).annotatedWith(named("one")); } }); install(new PrivateModule() { public void configure() { bind(String.class).annotatedWith(named("b")).toInstance("ii"); bind(AB.class).annotatedWith(named("two")).to(AB.class); expose(AB.class).annotatedWith(named("two")); } }); } }); AB ab1 = injector.getInstance(Key.get(AB.class, named("one"))); assertEquals("public", ab1.a); assertEquals("i", ab1.b); AB ab2 = injector.getInstance(Key.get(AB.class, named("two"))); assertEquals("public", ab2.a); assertEquals("ii", ab2.b); } public void testWithoutPrivateModules() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { PrivateBinder bindA = binder().newPrivateBinder(); bindA.bind(String.class).annotatedWith(named("a")).toInstance("i"); bindA.expose(String.class).annotatedWith(named("a")); bindA.bind(String.class).annotatedWith(named("c")).toInstance("private to A"); PrivateBinder bindB = binder().newPrivateBinder(); bindB.bind(String.class).annotatedWith(named("b")).toInstance("ii"); bindB.expose(String.class).annotatedWith(named("b")); bindB.bind(String.class).annotatedWith(named("c")).toInstance("private to B"); } }); assertEquals("i", injector.getInstance(Key.get(String.class, named("a")))); assertEquals("ii", injector.getInstance(Key.get(String.class, named("b")))); } public void testMisplacedExposedAnnotation() { try { Guice.createInjector(new AbstractModule() { protected void configure() {} @Provides @Exposed String provideString() { return "i"; } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "Cannot expose java.lang.String on a standard binder. ", "Exposed bindings are only applicable to private binders.", " at " + PrivateModuleTest.class.getName(), "provideString(PrivateModuleTest.java:"); } } public void testMisplacedExposeStatement() { try { Guice.createInjector(new AbstractModule() { protected void configure() { ((PrivateBinder) binder()).expose(String.class).annotatedWith(named("a")); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "Cannot expose java.lang.String on a standard binder. ", "Exposed bindings are only applicable to private binders.", " at " + PrivateModuleTest.class.getName(), "configure(PrivateModuleTest.java:"); } } public void testPrivateModulesAndProvidesMethods() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { install(new PrivateModule() { public void configure() { expose(String.class).annotatedWith(named("a")); } @Provides @Named("a") String providePublicA() { return "i"; } @Provides @Named("b") String providePrivateB() { return "private"; } }); install(new PrivateModule() { public void configure() {} @Provides @Named("c") String providePrivateC() { return "private"; } @Provides @Exposed @Named("d") String providePublicD() { return "ii"; } }); } }); assertEquals("i", injector.getInstance(Key.get(String.class, named("a")))); try { injector.getInstance(Key.get(String.class, named("b"))); fail(); } catch(ConfigurationException expected) { } try { injector.getInstance(Key.get(String.class, named("c"))); fail(); } catch(ConfigurationException expected) { } assertEquals("ii", injector.getInstance(Key.get(String.class, named("d")))); } public void testCannotBindAKeyExportedByASibling() { try { Guice.createInjector(new AbstractModule() { protected void configure() { install(new PrivateModule() { public void configure() { bind(String.class).toInstance("public"); expose(String.class); } }); install(new PrivateModule() { public void configure() { bind(String.class).toInstance("private"); } }); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "A binding to java.lang.String was already configured at ", getClass().getName(), ".configure(PrivateModuleTest.java:", " at " + getClass().getName(), ".configure(PrivateModuleTest.java:"); } } public void testExposeButNoBind() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).annotatedWith(named("a")).toInstance("a"); bind(String.class).annotatedWith(named("b")).toInstance("b"); install(new PrivateModule() { public void configure() { expose(AB.class); } }); } }); fail("AB was exposed but not bound"); } catch (CreationException expected) { assertContains(expected.getMessage(), "Could not expose() " + AB.class.getName() + ", it must be explicitly bound", ".configure(PrivateModuleTest.java:"); } } /** * Ensure that when we've got errors in different private modules, Guice presents all errors * in a unified message. */ public void testMessagesFromPrivateModulesAreNicelyIntegrated() { try { Guice.createInjector( new PrivateModule() { public void configure() { bind(C.class); } }, new PrivateModule() { public void configure() { bind(AB.class); } } ); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) No implementation for " + C.class.getName() + " was bound.", "at " + getClass().getName(), ".configure(PrivateModuleTest.java:", "2) No implementation for " + String.class.getName(), "Named(value=a) was bound.", "for field at " + AB.class.getName() + ".a(PrivateModuleTest.java:", "3) No implementation for " + String.class.getName(), "Named(value=b) was bound.", "for field at " + AB.class.getName() + ".b(PrivateModuleTest.java:", "3 errors"); } } public void testNestedPrivateInjectors() { Injector injector = Guice.createInjector(new PrivateModule() { public void configure() { expose(String.class); install(new PrivateModule() { public void configure() { bind(String.class).toInstance("nested"); expose(String.class); } }); } }); assertEquals("nested", injector.getInstance(String.class)); } public void testInstallingRegularModulesFromPrivateModules() { Injector injector = Guice.createInjector(new PrivateModule() { public void configure() { expose(String.class); install(new AbstractModule() { protected void configure() { bind(String.class).toInstance("nested"); } }); } }); assertEquals("nested", injector.getInstance(String.class)); } public void testNestedPrivateModulesWithSomeKeysUnexposed() { Injector injector = Guice.createInjector(new PrivateModule() { public void configure() { bind(String.class).annotatedWith(named("bound outer, exposed outer")).toInstance("boeo"); expose(String.class).annotatedWith(named("bound outer, exposed outer")); bind(String.class).annotatedWith(named("bound outer, exposed none")).toInstance("boen"); expose(String.class).annotatedWith(named("bound inner, exposed both")); install(new PrivateModule() { public void configure() { bind(String.class).annotatedWith(named("bound inner, exposed both")).toInstance("bieb"); expose(String.class).annotatedWith(named("bound inner, exposed both")); bind(String.class).annotatedWith(named("bound inner, exposed none")).toInstance("bien"); } }); } }); assertEquals("boeo", injector.getInstance(Key.get(String.class, named("bound outer, exposed outer")))); assertEquals("bieb", injector.getInstance(Key.get(String.class, named("bound inner, exposed both")))); try { injector.getInstance(Key.get(String.class, named("bound outer, exposed none"))); fail(); } catch (ConfigurationException expected) { } try { injector.getInstance(Key.get(String.class, named("bound inner, exposed none"))); fail(); } catch (ConfigurationException expected) { } } public void testDependenciesBetweenPrivateAndPublic() { Injector injector = Guice.createInjector( new PrivateModule() { protected void configure() {} @Provides @Exposed @Named("a") String provideA() { return "A"; } @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { return ab + "C"; } }, new AbstractModule() { protected void configure() {} @Provides @Named("ab") String provideAb(@Named("a") String a) { return a + "B"; } @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { return abc + "D"; } } ); assertEquals("ABCD", injector.getInstance(Key.get(String.class, named("abcd")))); } public void testDependenciesBetweenPrivateAndPublicWithPublicEagerSingleton() { Injector injector = Guice.createInjector( new PrivateModule() { protected void configure() {} @Provides @Exposed @Named("a") String provideA() { return "A"; } @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { return ab + "C"; } }, new AbstractModule() { protected void configure() { bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider() { @Inject @Named("abcd") String abcd; public String get() { return abcd + "E"; } }).asEagerSingleton(); } @Provides @Named("ab") String provideAb(@Named("a") String a) { return a + "B"; } @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { return abc + "D"; } } ); assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde")))); } public void testDependenciesBetweenPrivateAndPublicWithPrivateEagerSingleton() { Injector injector = Guice.createInjector( new AbstractModule() { protected void configure() {} @Provides @Named("ab") String provideAb(@Named("a") String a) { return a + "B"; } @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { return abc + "D"; } }, new PrivateModule() { protected void configure() { bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider() { @Inject @Named("abcd") String abcd; public String get() { return abcd + "E"; } }).asEagerSingleton(); expose(String.class).annotatedWith(named("abcde")); } @Provides @Exposed @Named("a") String provideA() { return "A"; } @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { return ab + "C"; } } ); assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde")))); } static class AB { @Inject @Named("a") String a; @Inject @Named("b") String b; } interface C {} public void testSpiAccess() { Injector injector = Guice.createInjector(new PrivateModule() { public void configure() { bind(String.class).annotatedWith(named("a")).toInstance("private"); bind(String.class).annotatedWith(named("b")).toInstance("exposed"); expose(String.class).annotatedWith(named("b")); } }); ExposedBinding binding = (ExposedBinding) injector.getBinding(Key.get(String.class, Names.named("b"))); assertEquals(ImmutableSet.>of(Dependency.get(Key.get(Injector.class))), binding.getDependencies()); PrivateElements privateElements = binding.getPrivateElements(); assertEquals(ImmutableSet.>of(Key.get(String.class, named("b"))), privateElements.getExposedKeys()); assertContains(privateElements.getExposedSource(Key.get(String.class, named("b"))).toString(), PrivateModuleTest.class.getName(), ".configure(PrivateModuleTest.java:"); Injector privateInjector = privateElements.getInjector(); assertEquals("private", privateInjector.getInstance(Key.get(String.class, Names.named("a")))); } public void testParentBindsSomethingInPrivate() { try { Guice.createInjector(new FailingModule()); fail(); } catch(CreationException expected) { assertEquals(1, expected.getErrorMessages().size()); assertContains(expected.toString(), "Unable to create binding for java.util.List.", "It was already configured on one or more child injectors or private modules", "bound at " + FailingPrivateModule.class.getName() + ".configure(", "bound at " + SecondFailingPrivateModule.class.getName() + ".configure(", "If it was in a PrivateModule, did you forget to expose the binding?", "at " + FailingModule.class.getName() + ".configure("); } } public void testParentBindingToPrivateLinkedJitBinding() { Injector injector = Guice.createInjector(new ManyPrivateModules()); try { injector.getBinding(Key.get(Types.providerOf(List.class))); fail(); } catch(ConfigurationException expected) { assertEquals(1, expected.getErrorMessages().size()); assertContains(expected.toString(), "Unable to create binding for com.google.inject.Provider.", "It was already configured on one or more child injectors or private modules", "bound at " + FailingPrivateModule.class.getName() + ".configure(", "bound at " + SecondFailingPrivateModule.class.getName() + ".configure(", "If it was in a PrivateModule, did you forget to expose the binding?", "while locating com.google.inject.Provider"); } } public void testParentBindingToPrivateJitBinding() { Injector injector = Guice.createInjector(new ManyPrivateModules()); try { injector.getBinding(PrivateFoo.class); fail(); } catch(ConfigurationException expected) { assertEquals(1, expected.getErrorMessages().size()); assertContains(expected.toString(), "Unable to create binding for " + PrivateFoo.class.getName(), "It was already configured on one or more child injectors or private modules", "(bound by a just-in-time binding)", "If it was in a PrivateModule, did you forget to expose the binding?", "while locating " + PrivateFoo.class.getName()); } } private static class FailingModule extends AbstractModule { @Override protected void configure() { bind(Collection.class).to(List.class); install(new ManyPrivateModules()); } } private static class ManyPrivateModules extends AbstractModule { @Override protected void configure() { // make sure duplicate sources are collapsed install(new FailingPrivateModule()); install(new FailingPrivateModule()); // but additional sources are listed install(new SecondFailingPrivateModule()); } } private static class FailingPrivateModule extends PrivateModule { @Override protected void configure() { bind(List.class).toInstance(new ArrayList()); // Add the Provider binding, created just-in-time, // to make sure our linked JIT bindings have the correct source. getProvider(Key.get(Types.providerOf(List.class))); // Request a JIT binding for PrivateFoo, which can only // be created in the private module because it depends // on List. getProvider(PrivateFoo.class); } } /** A second class, so we can see another name in the source list. */ private static class SecondFailingPrivateModule extends PrivateModule { @Override protected void configure() { bind(List.class).toInstance(new ArrayList()); // Add the Provider binding, created just-in-time, // to make sure our linked JIT bindings have the correct source. getProvider(Key.get(Types.providerOf(List.class))); // Request a JIT binding for PrivateFoo, which can only // be created in the private module because it depends // on List. getProvider(PrivateFoo.class); } } private static class PrivateFoo { @Inject List list; } } guice-3.0/core/test/com/google/inject/MembersInjectorTest.java0000644000175000017500000002246311460132772024366 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.name.Names; import com.google.inject.util.Providers; import java.util.concurrent.atomic.AtomicReference; import junit.framework.AssertionFailedError; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class MembersInjectorTest extends TestCase { private static final A uninjectableA = new A() { @Override void doNothing() { throw new AssertionFailedError(); } }; private static final B uninjectableB = new B() { @Override void doNothing() { throw new AssertionFailedError(); } }; private static final C myFavouriteC = new C(); public void testMembersInjectorFromBinder() { final AtomicReference>> aMembersInjectorReference = new AtomicReference>>(); final AtomicReference> bMembersInjectorReference = new AtomicReference>(); Guice.createInjector(new AbstractModule() { @Override protected void configure() { MembersInjector> aMembersInjector = getMembersInjector(new TypeLiteral>() {}); try { aMembersInjector.injectMembers(uninjectableA); fail(); } catch (IllegalStateException expected) { assertContains(expected.getMessage(), "This MembersInjector cannot be used until the Injector has been created."); } MembersInjector bMembersInjector = getMembersInjector(B.class); try { bMembersInjector.injectMembers(uninjectableB); fail(); } catch (IllegalStateException expected) { assertContains(expected.getMessage(), "This MembersInjector cannot be used until the Injector has been created."); } aMembersInjectorReference.set(aMembersInjector); bMembersInjectorReference.set(bMembersInjector); assertEquals("MembersInjector", getMembersInjector(String.class).toString()); bind(C.class).toInstance(myFavouriteC); } }); A injectableA = new A(); aMembersInjectorReference.get().injectMembers(injectableA); assertSame(myFavouriteC, injectableA.t); assertSame(myFavouriteC, injectableA.b.c); B injectableB = new B(); bMembersInjectorReference.get().injectMembers(injectableB); assertSame(myFavouriteC, injectableB.c); B anotherInjectableB = new B(); bMembersInjectorReference.get().injectMembers(anotherInjectableB); assertSame(myFavouriteC, anotherInjectableB.c); } public void testMembersInjectorFromInjector() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(C.class).toInstance(myFavouriteC); } }); MembersInjector> aMembersInjector = injector.getMembersInjector(new TypeLiteral>() {}); MembersInjector bMembersInjector = injector.getMembersInjector(B.class); A injectableA = new A(); aMembersInjector.injectMembers(injectableA); assertSame(myFavouriteC, injectableA.t); assertSame(myFavouriteC, injectableA.b.c); B injectableB = new B(); bMembersInjector.injectMembers(injectableB); assertSame(myFavouriteC, injectableB.c); B anotherInjectableB = new B(); bMembersInjector.injectMembers(anotherInjectableB); assertSame(myFavouriteC, anotherInjectableB.c); assertEquals("MembersInjector", injector.getMembersInjector(String.class).toString()); } public void testMembersInjectorWithNonInjectedTypes() { Injector injector = Guice.createInjector(); MembersInjector membersInjector = injector.getMembersInjector(NoInjectedMembers.class); membersInjector.injectMembers(new NoInjectedMembers()); membersInjector.injectMembers(new NoInjectedMembers()); } public void testInjectionFailure() { Injector injector = Guice.createInjector(); MembersInjector membersInjector = injector.getMembersInjector(InjectionFailure.class); try { membersInjector.injectMembers(new InjectionFailure()); fail(); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "1) Error injecting method, java.lang.ClassCastException: whoops, failure #1"); } } public void testInjectionAppliesToSpecifiedType() { Injector injector = Guice.createInjector(); MembersInjector membersInjector = injector.getMembersInjector(Object.class); membersInjector.injectMembers(new InjectionFailure()); } public void testInjectingMembersInjector() { InjectsMembersInjector injectsMembersInjector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(C.class).toInstance(myFavouriteC); } }).getInstance(InjectsMembersInjector.class); A a = new A(); injectsMembersInjector.aMembersInjector.injectMembers(a); assertSame(myFavouriteC, a.t); assertSame(myFavouriteC, a.b.c); } public void testCannotBindMembersInjector() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(MembersInjector.class).toProvider(Providers.of(null)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Binding to core guice framework type is not allowed: MembersInjector."); } try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(new TypeLiteral>>() {}) .toProvider(Providers.>>of(null)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Binding to core guice framework type is not allowed: MembersInjector."); } } public void testInjectingMembersInjectorWithErrorsInDependencies() { try { Guice.createInjector().getInstance(InjectsBrokenMembersInjector.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "1) No implementation for " + Unimplemented.class.getName() + " was bound.", "while locating " + Unimplemented.class.getName(), "for field at " + A.class.getName() + ".t(MembersInjectorTest.java:", "while locating com.google.inject.MembersInjector<", "for field at " + InjectsBrokenMembersInjector.class.getName() + ".aMembersInjector(", "while locating " + InjectsBrokenMembersInjector.class.getName()); } } public void testLookupMembersInjectorBinding() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(C.class).toInstance(myFavouriteC); } }); MembersInjector> membersInjector = injector.getInstance(new Key>>() {}); A a = new A(); membersInjector.injectMembers(a); assertSame(myFavouriteC, a.t); assertSame(myFavouriteC, a.b.c); assertEquals("MembersInjector", injector.getInstance(new Key>() {}).toString()); } public void testGettingRawMembersInjector() { Injector injector = Guice.createInjector(); try { injector.getInstance(MembersInjector.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "Cannot inject a MembersInjector that has no type parameter"); } } public void testGettingAnnotatedMembersInjector() { Injector injector = Guice.createInjector(); try { injector.getInstance(new Key>(Names.named("foo")) {}); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "1) No implementation for com.google.inject.MembersInjector " + "annotated with @com.google.inject.name.Named(value=foo) was bound."); } } static class A { @Inject B b; @Inject T t; @Inject void doNothing() {} } static class B { @Inject C c; @Inject void doNothing() {} } static class C {} static class NoInjectedMembers {} static class InjectionFailure { int failures = 0; @Inject void fail() { throw new ClassCastException("whoops, failure #" + (++failures)); } } static class InjectsMembersInjector { @Inject MembersInjector> aMembersInjector; @Inject A ab; } static class InjectsBrokenMembersInjector { @Inject MembersInjector> aMembersInjector; } static interface Unimplemented {} } guice-3.0/core/test/com/google/inject/name/0000755000175000017500000000000011460132764020505 5ustar drazzibdrazzibguice-3.0/core/test/com/google/inject/name/NamesTest.java0000644000175000017500000000722711460132764023263 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.name; import com.google.inject.AbstractModule; import static com.google.inject.Asserts.assertEqualWhenReserialized; import static com.google.inject.Asserts.assertEqualsBothWays; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.internal.util.ImmutableMap; import java.io.IOException; import java.util.Map; import java.util.Properties; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class NamesTest extends TestCase { @Named("foo") private String foo; private Named namedFoo; protected void setUp() throws Exception { super.setUp(); namedFoo = getClass().getDeclaredField("foo").getAnnotation(Named.class); } public void testConsistentEqualsAndHashcode() { Named actual = Names.named("foo"); assertEqualsBothWays(namedFoo, actual); assertEquals(namedFoo.toString(), actual.toString()); } public void testNamedIsSerializable() throws IOException { assertEqualWhenReserialized(Names.named("foo")); } public void testBindPropertiesUsingProperties() { final Properties teams = new Properties(); teams.setProperty("SanJose", "Sharks"); teams.setProperty("Edmonton", "Oilers"); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { Names.bindProperties(binder(), teams); } }); assertEquals("Sharks", injector.getInstance(Key.get(String.class, Names.named("SanJose")))); assertEquals("Oilers", injector.getInstance(Key.get(String.class, Names.named("Edmonton")))); } public void testBindPropertiesUsingMap() { final Map properties = ImmutableMap.of( "SanJose", "Sharks", "Edmonton", "Oilers"); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { Names.bindProperties(binder(), properties); } }); assertEquals("Sharks", injector.getInstance(Key.get(String.class, Names.named("SanJose")))); assertEquals("Oilers", injector.getInstance(Key.get(String.class, Names.named("Edmonton")))); } public void testBindPropertiesIncludesInheritedProperties() { Properties defaults = new Properties(); defaults.setProperty("Edmonton", "Eskimos"); defaults.setProperty("Regina", "Pats"); final Properties teams = new Properties(defaults); teams.setProperty("SanJose", "Sharks"); teams.setProperty("Edmonton", "Oilers"); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { Names.bindProperties(binder(), teams); } }); assertEquals("Pats", injector.getInstance(Key.get(String.class, Names.named("Regina")))); assertEquals("Oilers", injector.getInstance(Key.get(String.class, Names.named("Edmonton")))); assertEquals("Sharks", injector.getInstance(Key.get(String.class, Names.named("SanJose")))); try { injector.getInstance(Key.get(String.class, Names.named("Calgary"))); fail(); } catch (RuntimeException expected) { } } } guice-3.0/core/test/com/google/inject/name/NamedEquivalanceTest.java0000644000175000017500000002071111460132764025413 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.name; import static com.google.inject.Asserts.assertContains; import java.io.Serializable; import java.lang.annotation.Annotation; import java.util.Properties; import junit.framework.TestCase; import com.google.inject.AbstractModule; import com.google.inject.ConfigurationException; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provides; /** * Tests that {@code javax.inject.Named} and {@code com.google.inject.name.Named} are completely * interchangeable: bindings for one can be used to inject the other. * * @author cgdecker@gmail.com (Colin Decker) */ public class NamedEquivalanceTest extends TestCase { private static final Module GUICE_BINDING_MODULE = moduleWithAnnotation(Names.named("foo")); private static final Module JSR330_BINDING_MODULE = moduleWithAnnotation(new JsrNamed("foo")); private static final Module GUICE_PROVIDER_METHOD_MODULE = getGuiceBindingProviderMethodModule(); private static final Module JSR330_PROVIDER_METHOD_MODULE = getJsr330BindingProviderMethodModule(); public void testKeysCreatedWithDifferentTypesAreEqual() { assertEquals(keyForAnnotation(new GuiceNamed("foo")), keyForAnnotation(new JsrNamed("foo"))); assertEquals(keyForAnnotation(Names.named("foo")), keyForAnnotation(new GuiceNamed("foo"))); assertEquals(keyForAnnotation(Names.named("foo")), keyForAnnotation(new JsrNamed("foo"))); assertEquals(keyForAnnotationType(com.google.inject.name.Named.class), keyForAnnotationType(javax.inject.Named.class)); } private static Key keyForAnnotation(Annotation annotation) { return Key.get(String.class, annotation); } private static Key keyForAnnotationType(Class annotationType) { return Key.get(String.class, annotationType); } public void testBindingWithNamesCanInjectBothTypes() { assertInjectionsSucceed(GUICE_BINDING_MODULE); } public void testBindingWithJsr330AnnotationCanInjectBothTypes() { assertInjectionsSucceed(JSR330_BINDING_MODULE); } public void testBindingWithGuiceNamedAnnotatedProviderMethodCanInjectBothTypes() { assertInjectionsSucceed(GUICE_PROVIDER_METHOD_MODULE); } public void testBindingWithJsr330NamedAnnotatedProviderMethodCanInjectBothTypes() { assertInjectionsSucceed(JSR330_PROVIDER_METHOD_MODULE); } public void testBindingDifferentTypesWithSameValueIsIgnored() { assertDuplicateBinding(GUICE_BINDING_MODULE, JSR330_BINDING_MODULE, false); assertDuplicateBinding(JSR330_BINDING_MODULE, GUICE_BINDING_MODULE, false); } public void testBindingDifferentTypesWithSameValueIsAnErrorWithProviderMethods() { assertDuplicateBinding(GUICE_PROVIDER_METHOD_MODULE, JSR330_PROVIDER_METHOD_MODULE, true); assertDuplicateBinding(JSR330_PROVIDER_METHOD_MODULE, GUICE_PROVIDER_METHOD_MODULE, true); } public void testBindingDifferentTypesWithSameValueIsAnErrorMixed() { assertDuplicateBinding(GUICE_BINDING_MODULE, JSR330_PROVIDER_METHOD_MODULE, true); assertDuplicateBinding(JSR330_BINDING_MODULE, GUICE_PROVIDER_METHOD_MODULE, true); } public void testMissingBindingForGuiceNamedUsesSameTypeInErrorMessage() { assertMissingBindingErrorMessageUsesType(GuiceNamedClient.class); } public void testMissingBindingForJsr330NamedUsesSameTypeInErrorMessage() { assertMissingBindingErrorMessageUsesType(Jsr330NamedClient.class); } public void testBindPropertiesWorksWithJsr330() { assertInjectionsSucceed(new AbstractModule() { @Override protected void configure() { Properties properties = new Properties(); properties.put("foo", "bar"); Names.bindProperties(binder(), properties); } }); } private static void assertMissingBindingErrorMessageUsesType(Class clientType) { try { Guice.createInjector().getInstance(clientType); fail("should have thrown ConfigurationException"); } catch (ConfigurationException e) { assertContains(e.getMessage(), "No implementation for java.lang.String annotated with @com.google.inject.name.Named(value=foo) was bound."); } } private static void assertDuplicateBinding(Module a, Module b, boolean fails) { try { Guice.createInjector(a, b); if(fails) { fail("should have thrown CreationException"); } } catch (CreationException e) { if(fails) { assertContains(e.getMessage(), "A binding to java.lang.String annotated with @com.google.inject.name.Named(value=foo) was already configured"); } else { throw e; } } } private static Module moduleWithAnnotation(final Annotation annotation) { return new AbstractModule() { @Override protected void configure() { bindConstant().annotatedWith(annotation).to("bar"); } }; } private static void assertInjectionsSucceed(Module module) { Injector injector = Guice.createInjector(module); assertInjected(injector.getInstance(GuiceNamedClient.class), injector .getInstance(Jsr330NamedClient.class)); } private static void assertInjected(GuiceNamedClient guiceClient, Jsr330NamedClient jsr330Client) { assertEquals("bar", guiceClient.foo); assertEquals("bar", jsr330Client.foo); } private static Module getJsr330BindingProviderMethodModule() { return new AbstractModule() { @Override protected void configure() {} @SuppressWarnings("unused") @Provides @javax.inject.Named("foo") String provideFoo() { return "bar"; } }; } private static Module getGuiceBindingProviderMethodModule() { return new AbstractModule() { @Override protected void configure() {} @SuppressWarnings("unused") @Provides @Named("foo") String provideFoo() { return "bar"; } }; } private static class GuiceNamedClient { @Inject @Named("foo") String foo; } private static class Jsr330NamedClient { @Inject @javax.inject.Named("foo") String foo; } private static class JsrNamed implements javax.inject.Named, Serializable { private final String value; public JsrNamed(String value) { this.value = value; } public String value() { return this.value; } public int hashCode() { // This is specified in java.lang.Annotation. return (127 * "value".hashCode()) ^ value.hashCode(); } public boolean equals(Object o) { if (!(o instanceof javax.inject.Named)) { return false; } javax.inject.Named other = (javax.inject.Named) o; return value.equals(other.value()); } public String toString() { return "@" + javax.inject.Named.class.getName() + "(value=" + value + ")"; } public Class annotationType() { return javax.inject.Named.class; } private static final long serialVersionUID = 0; } private static class GuiceNamed implements com.google.inject.name.Named, Serializable { private final String value; public GuiceNamed(String value) { this.value = value; } public String value() { return this.value; } public int hashCode() { // This is specified in java.lang.Annotation. return (127 * "value".hashCode()) ^ value.hashCode(); } public boolean equals(Object o) { if (!(o instanceof com.google.inject.name.Named)) { return false; } com.google.inject.name.Named other = (com.google.inject.name.Named) o; return value.equals(other.value()); } public String toString() { return "@" + com.google.inject.name.Named.class.getName() + "(value=" + value + ")"; } public Class annotationType() { return com.google.inject.name.Named.class; } private static final long serialVersionUID = 0; } } guice-3.0/core/test/com/google/inject/NullableInjectionPointTest.java0000644000175000017500000001572311462362174025715 0ustar drazzibdrazzibpackage com.google.inject; import static com.google.inject.Asserts.assertContains; import java.lang.annotation.Annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.google.inject.internal.util.Nullable; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class NullableInjectionPointTest extends TestCase { public void testInjectNullIntoNotNullableConstructor() { try { createInjector().getInstance(FooConstructor.class); fail("Injecting null should fail with an error"); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "null returned by binding at " + getClass().getName(), "parameter 0 of " + FooConstructor.class.getName() + ".() is not @Nullable"); } } public void testInjectNullIntoNotNullableMethod() { try { createInjector().getInstance(FooMethod.class); fail("Injecting null should fail with an error"); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "null returned by binding at " + getClass().getName(), "parameter 0 of " + FooMethod.class.getName() + ".setFoo() is not @Nullable"); } } public void testInjectNullIntoNotNullableField() { try { createInjector().getInstance(FooField.class); fail("Injecting null should fail with an error"); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "null returned by binding at " + getClass().getName(), " but " + FooField.class.getName() + ".foo is not @Nullable"); } } /** * Provider.getInstance() is allowed to return null via direct calls to * getInstance(). */ public void testGetInstanceOfNull() { assertNull(createInjector().getInstance(Foo.class)); } public void testInjectNullIntoNullableConstructor() { NullableFooConstructor nfc = createInjector().getInstance(NullableFooConstructor.class); assertNull(nfc.foo); } public void testInjectNullIntoNullableMethod() { NullableFooMethod nfm = createInjector().getInstance(NullableFooMethod.class); assertNull(nfm.foo); } public void testInjectNullIntoNullableField() { NullableFooField nff = createInjector().getInstance(NullableFooField.class); assertNull(nff.foo); } public void testInjectNullIntoCustomNullableConstructor() { CustomNullableFooConstructor nfc = createInjector().getInstance(CustomNullableFooConstructor.class); assertNull(nfc.foo); } public void testInjectNullIntoCustomNullableMethod() { CustomNullableFooMethod nfm = createInjector().getInstance(CustomNullableFooMethod.class); assertNull(nfm.foo); } public void testInjectNullIntoCustomNullableField() { CustomNullableFooField nff = createInjector().getInstance(CustomNullableFooField.class); assertNull(nff.foo); } private Injector createInjector() { return Guice.createInjector( new AbstractModule() { protected void configure() { bind(Foo.class).toProvider(new Provider() { public Foo get() { return null; } }); } }); } /** * We haven't decided on what the desired behaviour of this test should be... */ public void testBindNullToInstance() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class).toInstance(null); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "Binding to null instances is not allowed.", "at " + getClass().getName(), ".configure(NullableInjectionPointTest.java:"); } } public void testBindNullToProvider() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class).toProvider(new Provider() { public Foo get() { return null; } }); } }); assertNull(injector.getInstance(NullableFooField.class).foo); assertNull(injector.getInstance(CustomNullableFooField.class).foo); try { injector.getInstance(FooField.class); } catch(ProvisionException expected) { assertContains(expected.getMessage(), "null returned by binding at"); } } public void testBindScopedNull() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class).toProvider(new Provider() { public Foo get() { return null; } }).in(Scopes.SINGLETON); } }); assertNull(injector.getInstance(NullableFooField.class).foo); assertNull(injector.getInstance(CustomNullableFooField.class).foo); try { injector.getInstance(FooField.class); } catch(ProvisionException expected) { assertContains(expected.getMessage(), "null returned by binding at"); } } public void testBindNullAsEagerSingleton() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class).toProvider(new Provider() { public Foo get() { return null; } }).asEagerSingleton(); } }); assertNull(injector.getInstance(NullableFooField.class).foo); assertNull(injector.getInstance(CustomNullableFooField.class).foo); try { injector.getInstance(FooField.class); fail(); } catch(ProvisionException expected) { assertContains(expected.getMessage(), "null returned by binding " + "at com.google.inject.NullableInjectionPointTest"); } } static class Foo { } static class FooConstructor { @Inject FooConstructor(Foo foo) { } } static class FooField { @Inject Foo foo; } static class FooMethod { @Inject void setFoo(Foo foo) { } } static class NullableFooConstructor { Foo foo; @Inject NullableFooConstructor(@Nullable Foo foo) { this.foo = foo; } } static class NullableFooField { @Inject @Nullable Foo foo; } static class NullableFooMethod { Foo foo; @Inject void setFoo(@Nullable Foo foo) { this.foo = foo; } } static class CustomNullableFooConstructor { Foo foo; @Inject CustomNullableFooConstructor(@Namespace.Nullable Foo foo) { this.foo = foo; } } static class CustomNullableFooField { @Inject @Namespace.Nullable Foo foo; } static class CustomNullableFooMethod { Foo foo; @Inject void setFoo(@Namespace.Nullable Foo foo) { this.foo = foo; } } static interface Namespace { @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.FIELD}) @interface Nullable { } } } guice-3.0/core/test/com/google/inject/TypeConversionTest.java0000644000175000017500000003400311533254604024256 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.internal.util.Iterables; import com.google.inject.matcher.Matchers; import com.google.inject.spi.ConvertedConstantBinding; import com.google.inject.spi.TypeConverter; import com.google.inject.spi.TypeConverterBinding; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.util.Date; import junit.framework.AssertionFailedError; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class TypeConversionTest extends TestCase { @Retention(RUNTIME) @BindingAnnotation @interface NumericValue {} @Retention(RUNTIME) @BindingAnnotation @interface BooleanValue {} @Retention(RUNTIME) @BindingAnnotation @interface EnumValue {} @Retention(RUNTIME) @BindingAnnotation @interface ClassName {} public static class Foo { @Inject @BooleanValue Boolean booleanField; @Inject @BooleanValue boolean primitiveBooleanField; @Inject @NumericValue Byte byteField; @Inject @NumericValue byte primitiveByteField; @Inject @NumericValue Short shortField; @Inject @NumericValue short primitiveShortField; @Inject @NumericValue Integer integerField; @Inject @NumericValue int primitiveIntField; @Inject @NumericValue Long longField; @Inject @NumericValue long primitiveLongField; @Inject @NumericValue Float floatField; @Inject @NumericValue float primitiveFloatField; @Inject @NumericValue Double doubleField; @Inject @NumericValue double primitiveDoubleField; @Inject @EnumValue Bar enumField; @Inject @ClassName Class classField; } public enum Bar { TEE, BAZ, BOB } public void testOneConstantInjection() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(NumericValue.class).to("5"); bind(Simple.class); } }); Simple simple = injector.getInstance(Simple.class); assertEquals(5, simple.i); } static class Simple { @Inject @NumericValue int i; } public void testConstantInjection() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(NumericValue.class).to("5"); bindConstant().annotatedWith(BooleanValue.class).to("true"); bindConstant().annotatedWith(EnumValue.class).to("TEE"); bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName()); } }); Foo foo = injector.getInstance(Foo.class); checkNumbers( foo.integerField, foo.primitiveIntField, foo.longField, foo.primitiveLongField, foo.byteField, foo.primitiveByteField, foo.shortField, foo.primitiveShortField, foo.floatField, foo.primitiveFloatField, foo.doubleField, foo.primitiveDoubleField ); assertEquals(Bar.TEE, foo.enumField); assertEquals(Foo.class, foo.classField); } public void testConstantInjectionWithExplicitBindingsRequired() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { binder().requireExplicitBindings(); bind(Foo.class); bindConstant().annotatedWith(NumericValue.class).to("5"); bindConstant().annotatedWith(BooleanValue.class).to("true"); bindConstant().annotatedWith(EnumValue.class).to("TEE"); bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName()); } }); Foo foo = injector.getInstance(Foo.class); checkNumbers( foo.integerField, foo.primitiveIntField, foo.longField, foo.primitiveLongField, foo.byteField, foo.primitiveByteField, foo.shortField, foo.primitiveShortField, foo.floatField, foo.primitiveFloatField, foo.doubleField, foo.primitiveDoubleField ); assertEquals(Bar.TEE, foo.enumField); assertEquals(Foo.class, foo.classField); } void checkNumbers(Number... ns) { for (Number n : ns) { assertEquals(5, n.intValue()); } } public void testInvalidInteger() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(NumericValue.class).to("invalid"); } }); try { injector.getInstance(InvalidInteger.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "Error converting 'invalid'"); assertContains(expected.getMessage(), "bound at " + getClass().getName()); assertContains(expected.getMessage(), "to java.lang.Integer"); } } public static class InvalidInteger { @Inject @NumericValue Integer integerField; } public void testInvalidCharacter() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(NumericValue.class).to("invalid"); } }); try { injector.getInstance(InvalidCharacter.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "Error converting 'invalid'"); assertContains(expected.getMessage(), "bound at " + getClass().getName()); assertContains(expected.getMessage(), "to java.lang.Character"); } } public static class InvalidCharacter { @Inject @NumericValue char foo; } public void testInvalidEnum() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(NumericValue.class).to("invalid"); } }); try { injector.getInstance(InvalidEnum.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "Error converting 'invalid'"); assertContains(expected.getMessage(), "bound at " + getClass().getName()); assertContains(expected.getMessage(), "to " + Bar.class.getName()); } } public static class InvalidEnum { @Inject @NumericValue Bar foo; } public void testToInstanceIsTreatedLikeConstant() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toInstance("5"); bind(LongHolder.class); } }); assertEquals(5L, (long) injector.getInstance(LongHolder.class).foo); } static class LongHolder { @Inject Long foo; } public void testCustomTypeConversion() throws CreationException { final Date result = new Date(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)) , mockTypeConverter(result)); bindConstant().annotatedWith(NumericValue.class).to("Today"); bind(DateHolder.class); } }); assertSame(result, injector.getInstance(DateHolder.class).date); Binding binding = injector.getBinding(Key.get(Date.class, NumericValue.class)); assertTrue(binding instanceof ConvertedConstantBinding); TypeConverterBinding converterBinding = ((ConvertedConstantBinding)binding).getTypeConverterBinding(); assertEquals("CustomConverter", converterBinding.getTypeConverter().toString()); assertTrue(injector.getTypeConverterBindings().contains(converterBinding)); } public void testInvalidCustomValue() throws CreationException { Module module = new AbstractModule() { protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), failingTypeConverter()); bindConstant().annotatedWith(NumericValue.class).to("invalid"); bind(DateHolder.class); } }; try { Guice.createInjector(module); fail(); } catch (CreationException expected) { Throwable cause = Iterables.getOnlyElement(expected.getErrorMessages()).getCause(); assertTrue(cause instanceof UnsupportedOperationException); assertContains(expected.getMessage(), "1) Error converting 'invalid' (bound at ", getClass().getName(), ".configure(TypeConversionTest.java:", "to java.util.Date", "using BrokenConverter which matches only(java.util.Date) ", "(bound at " + getClass().getName(), ".configure(TypeConversionTest.java:", "Reason: java.lang.UnsupportedOperationException: Cannot convert", "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:"); } } public void testNullCustomValue() { Module module = new AbstractModule() { protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(null)); bindConstant().annotatedWith(NumericValue.class).to("foo"); bind(DateHolder.class); } }; try { Guice.createInjector(module); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Received null converting 'foo' (bound at ", getClass().getName(), ".configure(TypeConversionTest.java:", "to java.util.Date", "using CustomConverter which matches only(java.util.Date) ", "(bound at " + getClass().getName(), ".configure(TypeConversionTest.java:", "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:"); } } public void testCustomValueTypeMismatch() { Module module = new AbstractModule() { protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(-1)); bindConstant().annotatedWith(NumericValue.class).to("foo"); bind(DateHolder.class); } }; try { Guice.createInjector(module); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Type mismatch converting 'foo' (bound at ", getClass().getName(), ".configure(TypeConversionTest.java:", "to java.util.Date", "using CustomConverter which matches only(java.util.Date) ", "(bound at " + getClass().getName(), ".configure(TypeConversionTest.java:", "Converter returned -1.", "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:"); } } public void testStringIsConvertedOnlyOnce() { final TypeConverter converter = new TypeConverter() { boolean converted = false; public Object convert(String value, TypeLiteral toType) { if (converted) { throw new AssertionFailedError("converted multiple times!"); } converted = true; return new Date(); } }; Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), converter); bindConstant().annotatedWith(NumericValue.class).to("unused"); } }); Date first = injector.getInstance(Key.get(Date.class, NumericValue.class)); Date second = injector.getInstance(Key.get(Date.class, NumericValue.class)); assertSame(first, second); } public void testAmbiguousTypeConversion() { Module module = new AbstractModule() { protected void configure() { convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(new Date())); convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(new Date())); bindConstant().annotatedWith(NumericValue.class).to("foo"); bind(DateHolder.class); } }; try { Guice.createInjector(module); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Multiple converters can convert 'foo' (bound at ", getClass().getName(), ".configure(TypeConversionTest.java:", "to java.util.Date:", "CustomConverter which matches only(java.util.Date)", "and", "CustomConverter which matches only(java.util.Date)", "Please adjust your type converter configuration to avoid overlapping matches.", "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:"); } } TypeConverter mockTypeConverter(final Object result) { return new TypeConverter() { public Object convert(String value, TypeLiteral toType) { return result; } @Override public String toString() { return "CustomConverter"; } }; } private TypeConverter failingTypeConverter() { return new TypeConverter() { public Object convert(String value, TypeLiteral toType) { throw new UnsupportedOperationException("Cannot convert"); } @Override public String toString() { return "BrokenConverter"; } }; } static class DateHolder { @Inject @NumericValue Date date; } public void testCannotConvertUnannotatedBindings() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toInstance("55"); } }); try { injector.getInstance(Integer.class); fail("Converted an unannotated String to an Integer"); } catch (ConfigurationException expected) { Asserts.assertContains(expected.getMessage(), "Could not find a suitable constructor in java.lang.Integer."); } } } guice-3.0/core/test/com/google/inject/GenericInjectionTest.java0000644000175000017500000001360011460132772024506 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.util.Modules; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class GenericInjectionTest extends TestCase { public void testGenericInjection() throws CreationException { final List names = Arrays.asList("foo", "bar", "bob"); Injector injector = Guice.createInjector((Module) new AbstractModule() { protected void configure() { bind(new TypeLiteral>() {}).toInstance(names); } }); Foo foo = injector.getInstance(Foo.class); assertEquals(names, foo.names); } static class Foo { @Inject List names; } /** * Although we may not have intended to support this behaviour, this test * passes under Guice 1.0. The workaround is to add an explicit binding for * the parameterized type. See {@link #testExplicitBindingOfGenericType()}. */ public void testImplicitBindingOfGenericType() { Parameterized parameterized = Guice.createInjector().getInstance(Key.get(new TypeLiteral>() {})); assertNotNull(parameterized); } public void testExplicitBindingOfGenericType() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Key.get(new TypeLiteral>() {})) .to((Class) Parameterized.class); } }); Parameterized parameterized = injector.getInstance(Key.get(new TypeLiteral>() { })); assertNotNull(parameterized); } static class Parameterized { @Inject Parameterized() { } } public void testInjectingParameterizedDependenciesForImplicitBinding() { assertParameterizedDepsInjected(new Key>() {}, Modules.EMPTY_MODULE); } public void testInjectingParameterizedDependenciesForBindingTarget() { final TypeLiteral> type = new TypeLiteral>() {}; assertParameterizedDepsInjected(Key.get(Object.class), new AbstractModule() { protected void configure() { bind(Object.class).to(type); } }); } public void testInjectingParameterizedDependenciesForBindingSource() { final TypeLiteral> type = new TypeLiteral>() {}; assertParameterizedDepsInjected(Key.get(type), new AbstractModule() { protected void configure() { bind(type); } }); } public void testBindingToSubtype() { final TypeLiteral> type = new TypeLiteral>() {}; assertParameterizedDepsInjected(Key.get(type), new AbstractModule() { protected void configure() { bind(type).to(new TypeLiteral>() {}); } }); } public void testBindingSubtype() { final TypeLiteral> type = new TypeLiteral>() {}; assertParameterizedDepsInjected(Key.get(type), new AbstractModule() { protected void configure() { bind(type); } }); } @SuppressWarnings("unchecked") public void assertParameterizedDepsInjected(Key key, Module bindingModule) { Module bindDataModule = new AbstractModule() { protected void configure() {} @Provides Map provideMap() { return ImmutableMap.of("one", 1, "two", 2); } @Provides Set provideSet(Map map) { return map.keySet(); } @Provides Collection provideCollection(Map map) { return map.values(); } }; Injector injector = Guice.createInjector(bindDataModule, bindingModule); ParameterizedDeps parameterizedDeps = (ParameterizedDeps) injector.getInstance(key); assertEquals(ImmutableMap.of("one", 1, "two", 2), parameterizedDeps.map); assertEquals(ImmutableSet.of("one", "two"), parameterizedDeps.keys); assertEquals(ImmutableSet.of(1, 2), ImmutableSet.copyOf(parameterizedDeps.values)); } static class SubParameterizedDeps extends ParameterizedDeps { @Inject SubParameterizedDeps(Set keys) { super(keys); } } static class ParameterizedDeps { @Inject private Map map; private Set keys; private Collection values; @Inject ParameterizedDeps(Set keys) { this.keys = keys; } @Inject void method(Collection values) { this.values = values; } } public void testImmediateTypeVariablesAreInjected() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toInstance("tee"); } }); InjectsT injectsT = injector.getInstance(new Key>() {}); assertEquals("tee", injectsT.t); } static class InjectsT { @Inject T t; } } guice-3.0/core/test/com/google/inject/BindingOrderTest.java0000644000175000017500000000525311460132772023642 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class BindingOrderTest extends TestCase { public void testBindingOutOfOrder() { Guice.createInjector(new AbstractModule() { protected void configure() { bind(BoundFirst.class); bind(BoundSecond.class).to(BoundSecondImpl.class); } }); } public static class BoundFirst { @Inject public BoundFirst(BoundSecond boundSecond) { } } interface BoundSecond { } static class BoundSecondImpl implements BoundSecond { } public void testBindingOrderAndScopes() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(A.class); bind(B.class).asEagerSingleton(); } }); assertSame(injector.getInstance(A.class).b, injector.getInstance(A.class).b); } public void testBindingWithExtraThreads() throws InterruptedException { final CountDownLatch ready = new CountDownLatch(1); final CountDownLatch done = new CountDownLatch(1); final AtomicReference ref = new AtomicReference(); final Object createsAThread = new Object() { @Inject void createAnotherThread(final Injector injector) { new Thread() { public void run() { ready.countDown(); A a = injector.getInstance(A.class); ref.set(a.b); done.countDown(); } }.start(); // to encourage collisions, we make sure the other thread is running before returning try { ready.await(); } catch (InterruptedException e) { throw new RuntimeException(e); } } }; Guice.createInjector(new AbstractModule() { protected void configure() { requestInjection(createsAThread); bind(A.class).toInstance(new A()); } }); done.await(); assertNotNull(ref.get()); } static class A { @Inject B b; } static class B { } } guice-3.0/core/test/com/google/inject/LoggerInjectionTest.java0000644000175000017500000000413011460132772024347 0ustar drazzibdrazzibpackage com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.name.Names; import java.util.logging.Logger; import junit.framework.TestCase; /** * Test built-in injection of loggers. * * @author jessewilson */ public class LoggerInjectionTest extends TestCase { @Inject Logger logger; public void testLoggerWithMember() { Injector injector = Guice.createInjector(); injector.injectMembers(this); assertEquals("com.google.inject.LoggerInjectionTest", logger.getName()); } public void testLoggerInConstructor() { Injector injector = Guice.createInjector(); Foo foo = injector.getInstance(Foo.class); assertEquals("com.google.inject.LoggerInjectionTest$Foo", foo.logger.getName()); } private static class Foo { Logger logger; @SuppressWarnings("unused") @Inject Foo(Logger logger) { this.logger = logger; } } public void testLoggerWithoutMember() { Injector injector = Guice.createInjector(); assertNull(injector.getInstance(Logger.class).getName()); assertNull(injector.getProvider(Logger.class).get().getName()); assertNull(injector.getBinding(Logger.class).getProvider().get().getName()); assertEquals("Provider", injector.getProvider(Logger.class).toString()); } public void testCanBindAnnotatedLogger() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Logger.class) .annotatedWith(Names.named("anonymous")) .toInstance(Logger.getAnonymousLogger()); } }); assertNull(injector.getInstance(Key.get(Logger.class, Names.named("anonymous"))).getName()); } public void testCannotBindLogger() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(Logger.class).toInstance(Logger.getAnonymousLogger()); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "A binding to java.util.logging.Logger was already configured"); } } } guice-3.0/core/test/com/google/inject/ProviderInjectionTest.java0000644000175000017500000001301511460132772024724 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.name.Named; import static com.google.inject.name.Names.named; import junit.framework.TestCase; import java.util.Arrays; import java.util.List; /** * @author crazybob@google.com (Bob Lee) */ public class ProviderInjectionTest extends TestCase { public void testProviderInjection() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Bar.class); bind(SampleSingleton.class).in(Scopes.SINGLETON); } }); Foo foo = injector.getInstance(Foo.class); Bar bar = foo.barProvider.get(); assertNotNull(bar); assertNotSame(bar, foo.barProvider.get()); SampleSingleton singleton = foo.singletonProvider.get(); assertNotNull(singleton); assertSame(singleton, foo.singletonProvider.get()); } /** Test for bug 155. */ public void testProvidersAreInjectedWhenBound() { Module m = new AbstractModule() { @Override protected void configure() { bind(Bar.class).toProvider(new Provider() { @SuppressWarnings("unused") @Inject void cantBeCalled(Baz baz) { fail("Can't have called this method since Baz is not bound."); } public Bar get() { return new Bar() {}; } }); } }; try { Guice.createInjector(m); fail("Should have thrown a CreationException"); } catch (CreationException expected) { } } /** * When custom providers are used at injector creation time, they should be * injected before use. In this testcase, we verify that a provider for * List.class is injected before it is used. */ public void testProvidersAreInjectedBeforeTheyAreUsed() { Injector injector = Guice.createInjector(new AbstractModule() { public void configure() { // should bind String to "[true]" bind(String.class).toProvider(new Provider() { private String value; @Inject void initialize(List list) { value = list.toString(); } public String get() { return value; } }); // should bind List to [true] bind(List.class).toProvider(new Provider() { @Inject Boolean injectedYet = Boolean.FALSE; public List get() { return Arrays.asList(injectedYet); } }); // should bind Boolean to true bind(Boolean.class).toInstance(Boolean.TRUE); } }); assertEquals("Providers not injected before use", "[true]", injector.getInstance(String.class)); } /** * This test ensures that regardless of binding order, instances are injected * before they are used. It injects mutable Count objects and records their * value at the time that they're injected. */ public void testCreationTimeInjectionOrdering() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { // instance injection bind(Count.class).annotatedWith(named("a")).toInstance(new Count(0) { @Inject void initialize(@Named("b") Count bCount) { value = bCount.value + 1; } }); // provider injection bind(Count.class).annotatedWith(named("b")).toProvider(new Provider() { Count count; @Inject void initialize(@Named("c") Count cCount) { count = new Count(cCount.value + 2); } public Count get() { return count; } }); // field and method injection, fields first bind(Count.class).annotatedWith(named("c")).toInstance(new Count(0) { @Inject @Named("d") Count dCount; @Inject void initialize(@Named("e") Count eCount) { value = dCount.value + eCount.value + 4; } }); // static injection requestStaticInjection(StaticallyInjectable.class); bind(Count.class).annotatedWith(named("d")).toInstance(new Count(8)); bind(Count.class).annotatedWith(named("e")).toInstance(new Count(16)); } }); assertEquals(28, injector.getInstance(Key.get(Count.class, named("c"))).value); assertEquals(30, injector.getInstance(Key.get(Count.class, named("b"))).value); assertEquals(31, injector.getInstance(Key.get(Count.class, named("a"))).value); assertEquals(28, StaticallyInjectable.cCountAtInjectionTime); } static class Count { int value; Count(int value) { this.value = value; } } static class StaticallyInjectable { static int cCountAtInjectionTime; @Inject static void initialize(@Named("c") Count cCount) { cCountAtInjectionTime = cCount.value; } } static class Foo { @Inject Provider barProvider; @Inject Provider singletonProvider; } static class Bar {} static class SampleSingleton {} interface Baz { } } guice-3.0/core/test/com/google/inject/MethodInterceptionTest.java0000644000175000017500000002102711533260020025062 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.Iterables; import com.google.inject.matcher.Matchers; import static com.google.inject.matcher.Matchers.only; import com.google.inject.spi.ConstructorBinding; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import junit.framework.TestCase; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * @author jessewilson@google.com (Jesse Wilson) */ public class MethodInterceptionTest extends TestCase { private AtomicInteger count = new AtomicInteger(); private final class CountingInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation methodInvocation) throws Throwable { count.incrementAndGet(); return methodInvocation.proceed(); } } private final class ReturnNullInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation methodInvocation) throws Throwable { return null; } } private final class NoOpInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation methodInvocation) throws Throwable { return methodInvocation.proceed(); } } public void testSharedProxyClasses() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class)), new ReturnNullInterceptor()); } }); Injector childOne = injector.createChildInjector(new AbstractModule() { protected void configure() { bind(Interceptable.class); } }); Interceptable nullFoosOne = childOne.getInstance(Interceptable.class); assertNotNull(nullFoosOne.bar()); assertNull(nullFoosOne.foo()); Injector childTwo = injector.createChildInjector(new AbstractModule() { protected void configure() { bind(Interceptable.class); } }); Interceptable nullFoosTwo = childTwo.getInstance(Interceptable.class); assertNull(nullFoosTwo.foo()); assertSame("Child injectors should share proxy classes, otherwise memory leaks!", nullFoosOne.getClass(), nullFoosTwo.getClass()); } public void testGetThis() { final AtomicReference lastTarget = new AtomicReference(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindInterceptor(Matchers.any(), Matchers.any(), new MethodInterceptor() { public Object invoke(MethodInvocation methodInvocation) throws Throwable { lastTarget.set(methodInvocation.getThis()); return methodInvocation.proceed(); } }); } }); Interceptable interceptable = injector.getInstance(Interceptable.class); interceptable.foo(); assertSame(interceptable, lastTarget.get()); } public void testInterceptingFinalClass() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindInterceptor(Matchers.any(), Matchers.any(), new MethodInterceptor() { public Object invoke(MethodInvocation methodInvocation) throws Throwable { return methodInvocation.proceed(); } }); } }); try { injector.getInstance(NotInterceptable.class); fail(); } catch(ConfigurationException ce) { assertEquals("Unable to method intercept: " + NotInterceptable.class.getName(), Iterables.getOnlyElement(ce.getErrorMessages()).getMessage().toString()); assertEquals("Cannot subclass final class class " + NotInterceptable.class.getName(), ce.getCause().getMessage()); } } public void testSpiAccessToInterceptors() throws NoSuchMethodException { final MethodInterceptor countingInterceptor = new CountingInterceptor(); final MethodInterceptor returnNullInterceptor = new ReturnNullInterceptor(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindInterceptor(Matchers.any(),Matchers.returns(only(Foo.class)), countingInterceptor); bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class).or(only(Bar.class))), returnNullInterceptor); } }); ConstructorBinding interceptedBinding = (ConstructorBinding) injector.getBinding(Interceptable.class); Method barMethod = Interceptable.class.getMethod("bar"); Method fooMethod = Interceptable.class.getMethod("foo"); assertEquals(ImmutableMap.>of( fooMethod, ImmutableList.of(countingInterceptor, returnNullInterceptor), barMethod, ImmutableList.of(returnNullInterceptor)), interceptedBinding.getMethodInterceptors()); ConstructorBinding nonInterceptedBinding = (ConstructorBinding) injector.getBinding(Foo.class); assertEquals(ImmutableMap.>of(), nonInterceptedBinding.getMethodInterceptors()); injector.getInstance(Interceptable.class).foo(); assertEquals("expected counting interceptor to be invoked first", 1, count.get()); } public void testInterceptedMethodThrows() throws Exception { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindInterceptor(Matchers.any(), Matchers.any(), new CountingInterceptor()); bindInterceptor(Matchers.any(), Matchers.any(), new CountingInterceptor()); } }); Interceptable interceptable = injector.getInstance(Interceptable.class); try { interceptable.explode(); fail(); } catch (Exception e) { // validate all causes. for (Throwable t = e; t != null; t = t.getCause()) { StackTraceElement[] stackTraceElement = t.getStackTrace(); assertEquals("explode", stackTraceElement[0].getMethodName()); assertEquals("invoke", stackTraceElement[1].getMethodName()); assertEquals("invoke", stackTraceElement[2].getMethodName()); assertEquals("testInterceptedMethodThrows", stackTraceElement[3].getMethodName()); } } } public void testNotInterceptedMethodsInInterceptedClassDontAddFrames() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class)), new NoOpInterceptor()); } }); Interceptable interceptable = injector.getInstance(Interceptable.class); assertNull(interceptable.lastElements); interceptable.foo(); boolean cglibFound = false; for (int i = 0; i < interceptable.lastElements.length; i++) { if (interceptable.lastElements[i].toString().contains("cglib")) { cglibFound = true; break; } } assertTrue(Arrays.asList(interceptable.lastElements).toString(), cglibFound); cglibFound = false; interceptable.bar(); for (int i = 0; i < interceptable.lastElements.length; i++) { if (interceptable.lastElements[i].toString().contains("cglib")) { cglibFound = true; break; } } assertFalse(Arrays.asList(interceptable.lastElements).toString(), cglibFound); } static class Foo {} static class Bar {} public static class Interceptable { StackTraceElement[] lastElements; public Foo foo() { lastElements = Thread.currentThread().getStackTrace(); return new Foo() {}; } public Bar bar() { lastElements = Thread.currentThread().getStackTrace(); return new Bar() {}; } public String explode() throws Exception { lastElements = Thread.currentThread().getStackTrace(); throw new Exception("kaboom!", new RuntimeException("boom!")); } } public static final class NotInterceptable {} } guice-3.0/core/test/com/google/inject/IntegrationTest.java0000644000175000017500000000344511460132772023560 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.matcher.Matchers.any; import junit.framework.TestCase; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * @author crazybob@google.com (Bob Lee) */ public class IntegrationTest extends TestCase { public void testIntegration() throws CreationException { final CountingInterceptor counter = new CountingInterceptor(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class); bindInterceptor(any(), any(), counter); } }); Foo foo = injector.getInstance(Key.get(Foo.class)); foo.foo(); assertTrue(foo.invoked); assertEquals(1, counter.count); foo = injector.getInstance(Foo.class); foo.foo(); assertTrue(foo.invoked); assertEquals(2, counter.count); } static class Foo { boolean invoked; public void foo() { invoked = true; } } static class CountingInterceptor implements MethodInterceptor { int count; public Object invoke(MethodInvocation methodInvocation) throws Throwable { count++; return methodInvocation.proceed(); } } } guice-3.0/core/test/com/google/inject/EagerSingletonTest.java0000644000175000017500000000466411460132772024207 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class EagerSingletonTest extends TestCase { @Override public void setUp() { A.instanceCount = 0; B.instanceCount = 0; C.instanceCount = 0; } public void testJustInTimeEagerSingletons() { Guice.createInjector(Stage.PRODUCTION, new AbstractModule() { protected void configure() { // create a just-in-time binding for A getProvider(A.class); // create a just-in-time binding for C requestInjection(new Object() { @Inject void inject(Injector injector) { injector.getInstance(C.class); } }); } }); assertEquals(1, A.instanceCount); assertEquals("Singletons discovered when creating singletons should not be built eagerly", 0, B.instanceCount); assertEquals(1, C.instanceCount); } public void testJustInTimeSingletonsAreNotEager() { Injector injector = Guice.createInjector(Stage.PRODUCTION); injector.getProvider(B.class); assertEquals(0, B.instanceCount); } public void testChildEagerSingletons() { Injector parent = Guice.createInjector(Stage.PRODUCTION); parent.createChildInjector(new AbstractModule() { @Override protected void configure() { bind(D.class).to(C.class); } }); assertEquals(1, C.instanceCount); } @Singleton static class A { static int instanceCount = 0; int instanceId = instanceCount++; @Inject A(Injector injector) { injector.getProvider(B.class); } } @Singleton static class B { static int instanceCount = 0; int instanceId = instanceCount++; } @Singleton static class C implements D { static int instanceCount = 0; int instanceId = instanceCount++; } private static interface D {} } guice-3.0/core/test/com/google/inject/DuplicateBindingsTest.java0000644000175000017500000005013411502222770024655 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import static com.google.inject.name.Names.named; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Objects; import com.google.inject.name.Named; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.logging.Logger; import junit.framework.TestCase; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; import com.google.inject.util.Providers; /** * A suite of tests for duplicate bindings. * * @author sameb@google.com (Sam Berlin) */ public class DuplicateBindingsTest extends TestCase { private FooImpl foo = new FooImpl(); private Provider pFoo = Providers.of(new FooImpl()); private Class> pclFoo = FooProvider.class; private Class clFoo = FooImpl.class; private Constructor cFoo = FooImpl.cxtor(); public void testDuplicateBindingsAreIgnored() { Injector injector = Guice.createInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo) ); List> bindings = Lists.newArrayList(injector.getAllBindings().keySet()); removeBasicBindings(bindings); // Ensure only one binding existed for each type. assertTrue(bindings.remove(Key.get(Foo.class, named("instance")))); assertTrue(bindings.remove(Key.get(Foo.class, named("pInstance")))); assertTrue(bindings.remove(Key.get(Foo.class, named("pKey")))); assertTrue(bindings.remove(Key.get(Foo.class, named("linkedKey")))); assertTrue(bindings.remove(Key.get(FooImpl.class))); assertTrue(bindings.remove(Key.get(Foo.class, named("constructor")))); assertTrue(bindings.remove(Key.get(FooProvider.class))); // JIT binding assertTrue(bindings.remove(Key.get(Foo.class, named("providerMethod")))); assertEquals(bindings.toString(), 0, bindings.size()); } public void testElementsDeduplicate() { List elements = Elements.getElements( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo) ); assertEquals(14, elements.size()); assertEquals(7, new LinkedHashSet(elements).size()); } public void testProviderMethodsFailIfInstancesDiffer() { try { Guice.createInjector(new FailingProviderModule(), new FailingProviderModule()); fail("should have failed"); } catch(CreationException ce) { assertContains(ce.getMessage(), "A binding to " + Foo.class.getName() + " was already configured at " + FailingProviderModule.class.getName(), "at " + FailingProviderModule.class.getName() ); } } public void testSameScopeInstanceIgnored() { Guice.createInjector( new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo), new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo) ); Guice.createInjector( new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo), new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo) ); } public void testSameScopeAnnotationIgnored() { Guice.createInjector( new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo), new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo) ); } public void testMixedAnnotationAndScopeForSingletonIgnored() { Guice.createInjector( new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo), new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo) ); } public void testMixedScopeAndUnscopedIgnored() { Guice.createInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo) ); } public void testMixedScopeFails() { try { Guice.createInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo) ); fail("expected exception"); } catch(CreationException ce) { assertContains(ce.getMessage(), "A binding to " + Foo.class.getName() + " annotated with " + named("pInstance") + " was already configured at " + SimpleModule.class.getName(), "at " + ScopedModule.class.getName(), "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") + " was already configured at " + SimpleModule.class.getName(), "at " + ScopedModule.class.getName(), "A binding to " + Foo.class.getName() + " annotated with " + named("linkedKey") + " was already configured at " + SimpleModule.class.getName(), "at " + ScopedModule.class.getName(), "A binding to " + FooImpl.class.getName() + " was already configured at " + SimpleModule.class.getName(), "at " + ScopedModule.class.getName(), "A binding to " + Foo.class.getName() + " annotated with " + named("constructor") + " was already configured at " + SimpleModule.class.getName(), "at " + ScopedModule.class.getName()); } } @SuppressWarnings("unchecked") public void testMixedTargetsFails() { try { Guice.createInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), new SimpleModule(new FooImpl(), Providers.of(new FooImpl()), (Class)BarProvider.class, (Class)Bar.class, (Constructor)Bar.cxtor()) ); fail("expected exception"); } catch(CreationException ce) { assertContains(ce.getMessage(), "A binding to " + Foo.class.getName() + " annotated with " + named("pInstance") + " was already configured at " + SimpleModule.class.getName(), "at " + SimpleModule.class.getName(), "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") + " was already configured at " + SimpleModule.class.getName(), "at " + SimpleModule.class.getName(), "A binding to " + Foo.class.getName() + " annotated with " + named("linkedKey") + " was already configured at " + SimpleModule.class.getName(), "at " + SimpleModule.class.getName(), "A binding to " + Foo.class.getName() + " annotated with " + named("constructor") + " was already configured at " + SimpleModule.class.getName(), "at " + SimpleModule.class.getName()); } } public void testExceptionInEqualsThrowsCreationException() { try { Guice.createInjector(new ThrowingModule(), new ThrowingModule()); fail("expected exception"); } catch(CreationException ce) { assertContains(ce.getMessage(), "A binding to " + Foo.class.getName() + " was already configured at " + ThrowingModule.class.getName(), "and an error was thrown while checking duplicate bindings. Error: java.lang.RuntimeException: Boo!", "at " + ThrowingModule.class.getName()); } } public void testChildInjectorDuplicateParentFail() { Injector injector = Guice.createInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo) ); try { injector.createChildInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo) ); fail("expected exception"); } catch(CreationException ce) { assertContains(ce.getMessage(), "A binding to " + Foo.class.getName() + " annotated with " + named("pInstance") + " was already configured at " + SimpleModule.class.getName(), "at " + SimpleModule.class.getName(), "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") + " was already configured at " + SimpleModule.class.getName(), "at " + SimpleModule.class.getName(), "A binding to " + Foo.class.getName() + " annotated with " + named("linkedKey") + " was already configured at " + SimpleModule.class.getName(), "at " + SimpleModule.class.getName(), "A binding to " + Foo.class.getName() + " annotated with " + named("constructor") + " was already configured at " + SimpleModule.class.getName(), "at " + SimpleModule.class.getName(), "A binding to " + Foo.class.getName() + " annotated with " + named("providerMethod") + " was already configured at " + SimpleProviderModule.class.getName(), "at " + SimpleProviderModule.class.getName() ); } } public void testDuplicatesSolelyInChildIgnored() { Injector injector = Guice.createInjector(); injector.createChildInjector( new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo), new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo) ); } public void testDifferentBindingTypesFail() { List elements = Elements.getElements( new FailedModule(foo, pFoo, pclFoo, clFoo, cFoo) ); // Make sure every combination of the elements with another element fails. // This ensures that duplication checks the kind of binding also. for(Element e1 : elements) { for(Element e2: elements) { // if they're the same, this shouldn't fail. try { Guice.createInjector(Elements.getModule(Arrays.asList(e1, e2))); if(e1 != e2) { fail("must fail!"); } } catch(CreationException expected) { if(e1 != e2) { assertContains(expected.getMessage(), "A binding to " + Foo.class.getName() + " was already configured at " + FailedModule.class.getName(), "at " + FailedModule.class.getName()); } else { throw expected; } } } } } public void testJitBindingsAreCheckedAfterConversions() { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(A.class); bind(A.class).to(RealA.class); } }); } public void testEqualsNotCalledByDefaultOnInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnEquals = true; Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class); bind(HashEqualsTester.class).toInstance(a); } }); } public void testEqualsNotCalledByDefaultOnProvider() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnEquals = true; Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class); bind(Object.class).toProvider(a); } }); } public void testHashcodeNeverCalledOnInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnHashcode = true; a.equality = "test"; final HashEqualsTester b = new HashEqualsTester(); b.throwOnHashcode = true; b.equality = "test"; Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class); bind(HashEqualsTester.class).toInstance(a); bind(HashEqualsTester.class).toInstance(b); } }); } public void testHashcodeNeverCalledOnProviderInstance() { final HashEqualsTester a = new HashEqualsTester(); a.throwOnHashcode = true; a.equality = "test"; final HashEqualsTester b = new HashEqualsTester(); b.throwOnHashcode = true; b.equality = "test"; Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class); bind(Object.class).toProvider(a); bind(Object.class).toProvider(b); } }); } private static class RealA extends A {} @ImplementedBy(RealA.class) private static class A {} private void removeBasicBindings(Collection> bindings) { bindings.remove(Key.get(Injector.class)); bindings.remove(Key.get(Logger.class)); bindings.remove(Key.get(Stage.class)); } private static class ThrowingModule extends AbstractModule { @Override protected void configure() { bind(Foo.class).toInstance(new Foo() { @Override public boolean equals(Object obj) { throw new RuntimeException("Boo!"); } }); } } private static abstract class FooModule extends AbstractModule { protected final FooImpl foo; protected final Provider pFoo; protected final Class> pclFoo; protected final Class clFoo; protected final Constructor cFoo; FooModule(FooImpl foo, Provider pFoo, Class> pclFoo, Class clFoo, Constructor cFoo) { this.foo = foo; this.pFoo = pFoo; this.pclFoo = pclFoo; this.clFoo = clFoo; this.cFoo = cFoo; } } private static class FailedModule extends FooModule { FailedModule(FooImpl foo, Provider pFoo, Class> pclFoo, Class clFoo, Constructor cFoo) { super(foo, pFoo, pclFoo, clFoo, cFoo); } protected void configure() { // InstanceBinding bind(Foo.class).toInstance(foo); // ProviderInstanceBinding bind(Foo.class).toProvider(pFoo); // ProviderKeyBinding bind(Foo.class).toProvider(pclFoo); // LinkedKeyBinding bind(Foo.class).to(clFoo); // ConstructorBinding bind(Foo.class).toConstructor(cFoo); } @Provides Foo foo() { return null; } } private static class FailingProviderModule extends AbstractModule { @Override protected void configure() {} @Provides Foo foo() { return null; } } private static class SimpleProviderModule extends AbstractModule { @Override protected void configure() {} @Provides @Named("providerMethod") Foo foo() { return null; } @Override public boolean equals(Object obj) { return obj.getClass() == getClass(); } } private static class SimpleModule extends FooModule { SimpleModule(FooImpl foo, Provider pFoo, Class> pclFoo, Class clFoo, Constructor cFoo) { super(foo, pFoo, pclFoo, clFoo, cFoo); } protected void configure() { // InstanceBinding bind(Foo.class).annotatedWith(named("instance")).toInstance(foo); // ProviderInstanceBinding bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo); // ProviderKeyBinding bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo); // LinkedKeyBinding bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo); // UntargettedBinding / ConstructorBinding bind(FooImpl.class); // ConstructorBinding bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo); // ProviderMethod // (reconstructed from an Element to ensure it doesn't get filtered out // by deduplicating Modules) install(Elements.getModule(Elements.getElements(new SimpleProviderModule()))); } } private static class ScopedModule extends FooModule { private final Scope scope; ScopedModule(Scope scope, FooImpl foo, Provider pFoo, Class> pclFoo, Class clFoo, Constructor cFoo) { super(foo, pFoo, pclFoo, clFoo, cFoo); this.scope = scope; } protected void configure() { // ProviderInstanceBinding bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope); // ProviderKeyBinding bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope); // LinkedKeyBinding bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope); // UntargettedBinding / ConstructorBinding bind(FooImpl.class).in(scope); // ConstructorBinding bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope); } } private static class AnnotatedScopeModule extends FooModule { private final Class scope; AnnotatedScopeModule(Class scope, FooImpl foo, Provider pFoo, Class> pclFoo, Class clFoo, Constructor cFoo) { super(foo, pFoo, pclFoo, clFoo, cFoo); this.scope = scope; } protected void configure() { // ProviderInstanceBinding bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope); // ProviderKeyBinding bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope); // LinkedKeyBinding bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope); // UntargettedBinding / ConstructorBinding bind(FooImpl.class).in(scope); // ConstructorBinding bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope); } } private static interface Foo {} private static class FooImpl implements Foo { @Inject public FooImpl() {} private static Constructor cxtor() { try { return FooImpl.class.getConstructor(); } catch (SecurityException e) { throw new RuntimeException(e); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } } } private static class FooProvider implements Provider { public Foo get() { return new FooImpl(); } } private static class Bar implements Foo { @Inject public Bar() {} private static Constructor cxtor() { try { return Bar.class.getConstructor(); } catch (SecurityException e) { throw new RuntimeException(e); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } } } private static class BarProvider implements Provider { public Foo get() { return new Bar(); } } private static class HashEqualsTester implements Provider { private String equality; private boolean throwOnEquals; private boolean throwOnHashcode; @Override public boolean equals(Object obj) { if (throwOnEquals) { throw new RuntimeException(); } else if (obj instanceof HashEqualsTester) { HashEqualsTester o = (HashEqualsTester)obj; if(o.throwOnEquals) { throw new RuntimeException(); } if(equality == null && o.equality == null) { return this == o; } else { return Objects.equal(equality, o.equality); } } else { return false; } } @Override public int hashCode() { if(throwOnHashcode) { throw new RuntimeException(); } else { return super.hashCode(); } } public Object get() { return new Object(); } } } guice-3.0/core/test/com/google/inject/internal/0000755000175000017500000000000011460132770021376 5ustar drazzibdrazzibguice-3.0/core/test/com/google/inject/internal/UniqueAnnotationsTest.java0000644000175000017500000000227311460132770026571 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import junit.framework.TestCase; import java.lang.annotation.Annotation; /** * @author jessewilson@google.com (Jesse Wilson) */ public class UniqueAnnotationsTest extends TestCase { @UniqueAnnotations.Internal(31) public Void unused; public void testEqualsHashCodeToString() { Annotation actual = UniqueAnnotations.create(31); Annotation expected = getClass().getFields()[0].getAnnotations()[0]; assertEquals(expected.toString(), actual.toString()); assertEquals(expected.hashCode(), actual.hashCode()); assertEquals(expected, actual); } } guice-3.0/core/test/com/google/inject/internal/ProxyFactoryTest.java0000644000175000017500000001366211460132770025562 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Inject; import static com.google.inject.matcher.Matchers.annotatedWith; import static com.google.inject.matcher.Matchers.any; import static com.google.inject.matcher.Matchers.not; import static com.google.inject.matcher.Matchers.only; import com.google.inject.internal.util.Lists; import com.google.inject.spi.InjectionPoint; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.InvocationTargetException; import java.util.List; import junit.framework.TestCase; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * @author crazybob@google.com (Bob Lee) */ public class ProxyFactoryTest extends TestCase { List aspects = Lists.newArrayList(); public void testSimpleCase() throws NoSuchMethodException, InvocationTargetException, ErrorsException { SimpleInterceptor interceptor = new SimpleInterceptor(); InjectionPoint injectionPoint = InjectionPoint.forConstructorOf(Simple.class); aspects.add(new MethodAspect(any(), any(), interceptor)); ProxyFactory factory = new ProxyFactory(injectionPoint, aspects); ConstructionProxy constructionProxy = factory.create(); Simple simple = constructionProxy.newInstance(); simple.invoke(); assertTrue(simple.invoked); assertTrue(interceptor.invoked); } static class Simple { boolean invoked = false; public void invoke() { invoked = true; } } static class SimpleInterceptor implements MethodInterceptor { boolean invoked = false; public Object invoke(MethodInvocation methodInvocation) throws Throwable { invoked = true; return methodInvocation.proceed(); } } public void testInterceptOneMethod() throws NoSuchMethodException, InvocationTargetException, ErrorsException { SimpleInterceptor interceptor = new SimpleInterceptor(); aspects.add(new MethodAspect(only(Bar.class), annotatedWith(Intercept.class), interceptor)); ConstructionProxy fooFactory = new ProxyFactory(InjectionPoint.forConstructorOf(Foo.class), aspects).create(); ConstructionProxy barFactory = new ProxyFactory(InjectionPoint.forConstructorOf(Bar.class), aspects).create(); Foo foo = fooFactory.newInstance(); Bar bar = barFactory.newInstance(); foo.foo(); assertTrue(foo.fooCalled); assertFalse(interceptor.invoked); bar.bar(); assertTrue(bar.barCalled); assertFalse(interceptor.invoked); bar.intercepted(); assertTrue(bar.interceptedCalled); assertTrue(interceptor.invoked); } static class Foo { boolean fooCalled; @Intercept void foo() { fooCalled = true; } } static class Bar { boolean barCalled; void bar() { barCalled = true; } boolean interceptedCalled; @Intercept void intercepted() { interceptedCalled = true; } } @Retention(RetentionPolicy.RUNTIME) @interface Intercept {} public void testWithConstructorArguments() throws InvocationTargetException, NoSuchMethodException, ErrorsException { SimpleInterceptor interceptor = new SimpleInterceptor(); aspects.add(new MethodAspect(any(), any(), interceptor)); ProxyFactory factory = new ProxyFactory(InjectionPoint.forConstructorOf(A.class), aspects); ConstructionProxy constructor = factory.create(); A a = constructor.newInstance(5); a.a(); assertEquals(5, a.i); } public void testNotProxied() throws NoSuchMethodException, InvocationTargetException, ErrorsException { SimpleInterceptor interceptor = new SimpleInterceptor(); aspects.add(new MethodAspect(not(any()), not(any()), interceptor)); ProxyFactory factory = new ProxyFactory(InjectionPoint.forConstructorOf(A.class), aspects); ConstructionProxy constructor = factory.create(); A a = constructor.newInstance(5); assertEquals(A.class, a.getClass()); } static class A { final int i; @Inject public A(int i) { this.i = i; } public void a() {} } public void testMultipleInterceptors() throws NoSuchMethodException, InvocationTargetException, ErrorsException { DoubleInterceptor doubleInterceptor = new DoubleInterceptor(); CountingInterceptor countingInterceptor = new CountingInterceptor(); aspects.add(new MethodAspect(any(), any(), doubleInterceptor, countingInterceptor)); ProxyFactory factory = new ProxyFactory(InjectionPoint.forConstructorOf(Counter.class), aspects); ConstructionProxy constructor = factory.create(); Counter counter = constructor.newInstance(); counter.inc(); assertEquals(2, counter.count); assertEquals(2, countingInterceptor.count); } static class CountingInterceptor implements MethodInterceptor { int count; public Object invoke(MethodInvocation methodInvocation) throws Throwable { count++; return methodInvocation.proceed(); } } static class DoubleInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation methodInvocation) throws Throwable { methodInvocation.proceed(); return methodInvocation.proceed(); } } static class Counter { int count; void inc() { count++; } } } guice-3.0/core/test/com/google/inject/internal/MoreTypesTest.java0000644000175000017500000000353111460132770025032 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.TypeLiteral; import java.util.Map; import java.util.Set; import junit.framework.TestCase; /** * @author schmitt@google.com (Peter Schmitt) */ public class MoreTypesTest extends TestCase { public void testParameterizedTypeToString() { TypeLiteral> innerString = new TypeLiteral>(){}; assertEquals("com.google.inject.internal.MoreTypesTest$Inner", MoreTypes.typeToString(innerString.getType())); TypeLiteral>> mapInnerInteger = new TypeLiteral>>() {}; assertEquals("java.util.Set>", MoreTypes.typeToString(mapInnerInteger.getType())); TypeLiteral, Set>>> mapInnerLongToSetInnerLong = new TypeLiteral, Set>>>() {}; assertEquals("java.util.Map, " + "java.util.Set>>", MoreTypes.typeToString(mapInnerLongToSetInnerLong.getType())); } public static class Inner {} } guice-3.0/core/test/com/google/inject/internal/util/0000755000175000017500000000000011501135042022342 5ustar drazzibdrazzibguice-3.0/core/test/com/google/inject/internal/util/ForwardingConcurrentMap.java0000644000175000017500000000310211460132770030015 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.concurrent.ConcurrentMap; /** * A concurrent map which forwards all its method calls to another concurrent * map. Subclasses should override one or more methods to modify the behavior of * the backing map as desired per the decorator pattern. * * @see ForwardingObject * @author Charles Fry */ public abstract class ForwardingConcurrentMap extends ForwardingMap implements ConcurrentMap { @Override protected abstract ConcurrentMap delegate(); public V putIfAbsent(K key, V value) { return delegate().putIfAbsent(key, value); } public boolean remove(Object key, Object value) { return delegate().remove(key, value); } public V replace(K key, V value) { return delegate().replace(key, value); } public boolean replace(K key, V oldValue, V newValue) { return delegate().replace(key, oldValue, newValue); } } guice-3.0/core/test/com/google/inject/internal/util/Jsr166HashMapTest.java0000644000175000017500000004205311460132770026317 0ustar drazzibdrazzib/* * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at * http://creativecommons.org/licenses/publicdomain * Other contributors include Andrew Wright, Jeffrey Hayes, * Pat Fisher, Mike Judd. */ package com.google.inject.internal.util; import com.google.inject.internal.util.Jsr166HashMap; import junit.framework.TestCase; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * ConcurrentHashMap tests copied from ConcurrentHashMapTest. Useful as a * test case for CustomConcurrentHashMap. */ public class Jsr166HashMapTest extends TestCase { /* * The following two methods and constants were copied from JSR166TestCase. */ /** * fail with message "should throw exception" */ public void shouldThrow() { fail("Should throw exception"); } /** * fail with message "Unexpected exception" */ public void unexpectedException() { fail("Unexpected exception"); } static final Integer zero = new Integer(0); static final Integer one = new Integer(1); static final Integer two = new Integer(2); static final Integer three = new Integer(3); static final Integer four = new Integer(4); static final Integer five = new Integer(5); static final Integer six = new Integer(6); static final Integer seven = new Integer(7); static final Integer eight = new Integer(8); static final Integer nine = new Integer(9); static final Integer m1 = new Integer(-1); static final Integer m2 = new Integer(-2); static final Integer m3 = new Integer(-3); static final Integer m4 = new Integer(-4); static final Integer m5 = new Integer(-5); static final Integer m6 = new Integer(-6); static final Integer m10 = new Integer(-10); /** * Create a map from Integers 1-5 to Strings "A"-"E". */ private static Jsr166HashMap map5() { Jsr166HashMap map = new Jsr166HashMap(5); assertTrue(map.isEmpty()); map.put(one, "A"); map.put(two, "B"); map.put(three, "C"); map.put(four, "D"); map.put(five, "E"); assertFalse(map.isEmpty()); assertEquals(5, map.size()); return map; } /** * clear removes all pairs */ public void testClear() { Jsr166HashMap map = map5(); map.clear(); assertEquals(map.size(), 0); } /** * Maps with same contents are equal */ public void testEquals() { Jsr166HashMap map1 = map5(); Jsr166HashMap map2 = map5(); assertEquals(map1, map2); assertEquals(map2, map1); map1.clear(); assertFalse(map1.equals(map2)); assertFalse(map2.equals(map1)); } /** * containsKey returns true for contained key */ public void testContainsKey() { Jsr166HashMap map = map5(); assertTrue(map.containsKey(one)); assertFalse(map.containsKey(zero)); } /** * containsValue returns true for held values */ public void testContainsValue() { Jsr166HashMap map = map5(); assertTrue(map.containsValue("A")); assertFalse(map.containsValue("Z")); } /** * get returns the correct element at the given key, or null if not present */ public void testGet() { Jsr166HashMap map = map5(); assertEquals("A", (String) map.get(one)); Jsr166HashMap empty = new Jsr166HashMap(); assertNull(map.get("anything")); } /** * isEmpty is true of empty map and false for non-empty */ public void testIsEmpty() { Jsr166HashMap empty = new Jsr166HashMap(); Jsr166HashMap map = map5(); assertTrue(empty.isEmpty()); assertFalse(map.isEmpty()); } /** * keySet returns a Set containing all the keys */ public void testKeySet() { Jsr166HashMap map = map5(); Set s = map.keySet(); assertEquals(5, s.size()); assertTrue(s.contains(one)); assertTrue(s.contains(two)); assertTrue(s.contains(three)); assertTrue(s.contains(four)); assertTrue(s.contains(five)); } /** * keySet.toArray returns contains all keys */ public void testKeySetToArray() { Jsr166HashMap map = map5(); Set s = map.keySet(); Object[] ar = s.toArray(); assertTrue(s.containsAll(Arrays.asList(ar))); assertEquals(5, ar.length); ar[0] = m10; assertFalse(s.containsAll(Arrays.asList(ar))); } /** * Values.toArray contains all values */ public void testValuesToArray() { Jsr166HashMap map = map5(); Collection v = map.values(); Object[] ar = v.toArray(); ArrayList s = new ArrayList(Arrays.asList(ar)); assertEquals(5, ar.length); assertTrue(s.contains("A")); assertTrue(s.contains("B")); assertTrue(s.contains("C")); assertTrue(s.contains("D")); assertTrue(s.contains("E")); } /** * entrySet.toArray contains all entries */ public void testEntrySetToArray() { Jsr166HashMap map = map5(); Set s = map.entrySet(); Object[] ar = s.toArray(); assertEquals(5, ar.length); for (int i = 0; i < 5; ++i) { assertTrue(map.containsKey(((Map.Entry) (ar[i])).getKey())); assertTrue(map.containsValue(((Map.Entry) (ar[i])).getValue())); } } /** * values collection contains all values */ public void testValues() { Jsr166HashMap map = map5(); Collection s = map.values(); assertEquals(5, s.size()); assertTrue(s.contains("A")); assertTrue(s.contains("B")); assertTrue(s.contains("C")); assertTrue(s.contains("D")); assertTrue(s.contains("E")); } /** * entrySet contains all pairs */ public void testEntrySet() { Jsr166HashMap map = map5(); Set s = map.entrySet(); assertEquals(5, s.size()); Iterator it = s.iterator(); while (it.hasNext()) { Map.Entry e = (Map.Entry) it.next(); assertTrue( (e.getKey().equals(one) && e.getValue().equals("A")) || (e.getKey().equals(two) && e.getValue().equals("B")) || (e.getKey().equals(three) && e.getValue() .equals("C")) || (e.getKey().equals(four) && e.getValue() .equals("D")) || (e.getKey().equals(five) && e.getValue() .equals("E"))); } } /** * putAll adds all key-value pairs from the given map */ public void testPutAll() { Jsr166HashMap empty = new Jsr166HashMap(); Jsr166HashMap map = map5(); empty.putAll(map); assertEquals(5, empty.size()); assertTrue(empty.containsKey(one)); assertTrue(empty.containsKey(two)); assertTrue(empty.containsKey(three)); assertTrue(empty.containsKey(four)); assertTrue(empty.containsKey(five)); } /** * putIfAbsent works when the given key is not present */ public void testPutIfAbsent() { Jsr166HashMap map = map5(); map.putIfAbsent(six, "Z"); assertTrue(map.containsKey(six)); } /** * putIfAbsent does not add the pair if the key is already present */ public void testPutIfAbsent2() { Jsr166HashMap map = map5(); assertEquals("A", map.putIfAbsent(one, "Z")); } /** * replace fails when the given key is not present */ public void testReplace() { Jsr166HashMap map = map5(); assertNull(map.replace(six, "Z")); assertFalse(map.containsKey(six)); } /** * replace succeeds if the key is already present */ public void testReplace2() { Jsr166HashMap map = map5(); assertNotNull(map.replace(one, "Z")); assertEquals("Z", map.get(one)); } /** * replace value fails when the given key not mapped to expected value */ public void testReplaceValue() { Jsr166HashMap map = map5(); assertEquals("A", map.get(one)); assertFalse(map.replace(one, "Z", "Z")); assertEquals("A", map.get(one)); } /** * replace value succeeds when the given key mapped to expected value */ public void testReplaceValue2() { Jsr166HashMap map = map5(); assertEquals("A", map.get(one)); assertTrue(map.replace(one, "A", "Z")); assertEquals("Z", map.get(one)); } /** * remove removes the correct key-value pair from the map */ public void testRemove() { Jsr166HashMap map = map5(); map.remove(five); assertEquals(4, map.size()); assertFalse(map.containsKey(five)); } /** * remove(key,value) removes only if pair present */ public void testRemove2() { Jsr166HashMap map = map5(); map.remove(five, "E"); assertEquals(4, map.size()); assertFalse(map.containsKey(five)); map.remove(four, "A"); assertEquals(4, map.size()); assertTrue(map.containsKey(four)); } /** * size returns the correct values */ public void testSize() { Jsr166HashMap map = map5(); Jsr166HashMap empty = new Jsr166HashMap(); assertEquals(0, empty.size()); assertEquals(5, map.size()); } /** * toString contains toString of elements */ public void testToString() { Jsr166HashMap map = map5(); String s = map.toString(); for (int i = 1; i <= 5; ++i) { assertTrue(s.indexOf(String.valueOf(i)) >= 0); } } // Exception tests /** * Cannot create with negative capacity */ public void testConstructor1() { try { new Jsr166HashMap(-1, 0, 1); shouldThrow(); } catch (IllegalArgumentException e) { } } /** * Cannot create with negative concurrency level */ public void testConstructor2() { try { new Jsr166HashMap(1, 0, -1); shouldThrow(); } catch (IllegalArgumentException e) { } } /** * Cannot create with only negative capacity */ public void testConstructor3() { try { new Jsr166HashMap(-1); shouldThrow(); } catch (IllegalArgumentException e) { } } /** * get(null) throws NPE */ public void testGet_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.get(null); shouldThrow(); } catch (NullPointerException e) { } } /** * containsKey(null) throws NPE */ public void testContainsKey_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.containsKey(null); shouldThrow(); } catch (NullPointerException e) { } } /** * containsValue(null) throws NPE */ public void testContainsValue_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.containsValue(null); shouldThrow(); } catch (NullPointerException e) { } } /** * put(null,x) throws NPE */ public void testPut1_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.put(null, "whatever"); shouldThrow(); } catch (NullPointerException e) { } } /** * put(x, null) throws NPE */ public void testPut2_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.put("whatever", null); shouldThrow(); } catch (NullPointerException e) { } } /** * putIfAbsent(null, x) throws NPE */ public void testPutIfAbsent1_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.putIfAbsent(null, "whatever"); shouldThrow(); } catch (NullPointerException e) { } } /** * replace(null, x) throws NPE */ public void testReplace_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.replace(null, "whatever"); shouldThrow(); } catch (NullPointerException e) { } } /** * replace(null, x, y) throws NPE */ public void testReplaceValue_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.replace(null, one, "whatever"); shouldThrow(); } catch (NullPointerException e) { } } /** * putIfAbsent(x, null) throws NPE */ public void testPutIfAbsent2_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.putIfAbsent("whatever", null); shouldThrow(); } catch (NullPointerException e) { } } /** * replace(x, null) throws NPE */ public void testReplace2_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.replace("whatever", null); shouldThrow(); } catch (NullPointerException e) { } } /** * replace(x, null, y) throws NPE */ public void testReplaceValue2_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.replace("whatever", null, "A"); shouldThrow(); } catch (NullPointerException e) { } } /** * replace(x, y, null) throws NPE */ public void testReplaceValue3_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.replace("whatever", one, null); shouldThrow(); } catch (NullPointerException e) { } } /** * remove(null) throws NPE */ public void testRemove1_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.put("sadsdf", "asdads"); c.remove(null); shouldThrow(); } catch (NullPointerException e) { } } /** * remove(null, x) throws NPE */ public void testRemove2_NullPointerException() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.put("sadsdf", "asdads"); c.remove(null, "whatever"); shouldThrow(); } catch (NullPointerException e) { } } /** * remove(x, null) returns false */ public void testRemove3() { try { Jsr166HashMap c = new Jsr166HashMap(5); c.put("sadsdf", "asdads"); assertFalse(c.remove("sadsdf", null)); } catch (NullPointerException e) { fail(); } } /** * A deserialized map equals original */ public void testSerialization() { Jsr166HashMap q = map5(); try { ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); out.writeObject(q); out.close(); ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); Jsr166HashMap r = (Jsr166HashMap) in.readObject(); assertEquals(q.size(), r.size()); assertTrue(q.equals(r)); assertTrue(r.equals(q)); } catch (Exception e) { e.printStackTrace(); unexpectedException(); } } /** * SetValue of an EntrySet entry sets value in the map. */ public void testSetValueWriteThrough() { // Adapted from a bug report by Eric Zoerner Jsr166HashMap map = new Jsr166HashMap(2, 5.0f, 1); assertTrue(map.isEmpty()); for (int i = 0; i < 20; i++) { map.put(new Integer(i), new Integer(i)); } assertFalse(map.isEmpty()); Map.Entry entry1 = (Map.Entry) map.entrySet().iterator().next(); // assert that entry1 is not 16 assertTrue("entry is 16, test not valid", !entry1.getKey().equals(new Integer(16))); // remove 16 (a different key) from map // which just happens to cause entry1 to be cloned in map map.remove(new Integer(16)); entry1.setValue("XYZ"); assertTrue(map.containsValue("XYZ")); // fails } } guice-3.0/core/test/com/google/inject/internal/util/MapMakerTestSuite.java0000644000175000017500000010671311461631440026574 0ustar drazzibdrazzib/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import com.google.inject.internal.util.ComputationException; import com.google.inject.internal.util.CustomConcurrentHashMap.Impl; import com.google.inject.internal.util.ExpirationTimer; import com.google.inject.internal.util.MapMaker; import com.google.inject.internal.util.Maps; import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Unit tests for MapMaker. Also less directly serves as the test suite for * CustomConcurrentHashMap. */ public class MapMakerTestSuite extends TestCase { public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(MakerTest.class); suite.addTestSuite(RecursiveComputationTest.class); suite.addTestSuite(ReferenceMapTest.class); suite.addTestSuite(ComputingTest.class); suite.addTest(ReferenceCombinationTestSuite.suite()); suite.addTestSuite(ExpiringReferenceMapTest.class); suite.addTestSuite(ExpiringComputingReferenceMapTest.class); return suite; } public static class MakerTest extends TestCase { public void testSizingDefaults() { Impl map = makeCustomMap(new MapMaker()); assertEquals(16, map.segments.length); // concurrency level assertEquals(1, map.segments[0].table.length()); // capacity / conc level assertEquals(0.75f, map.loadFactor); } public void testInitialCapacity_small() { MapMaker maker = new MapMaker().initialCapacity(17); Impl map = makeCustomMap(maker); assertEquals(2, map.segments[0].table.length()); } public void testInitialCapacity_smallest() { MapMaker maker = new MapMaker().initialCapacity(0); Impl map = makeCustomMap(maker); // 1 is as low as it goes, not 0. it feels dirty to know this/test this. assertEquals(1, map.segments[0].table.length()); } public void testInitialCapacity_large() { new MapMaker().initialCapacity(Integer.MAX_VALUE); // that the maker didn't blow up is enough; // don't actually create this monster! } public void testInitialCapacity_negative() { MapMaker maker = new MapMaker(); try { maker.initialCapacity(-1); fail(); } catch (IllegalArgumentException expected) { } } // TODO: enable when ready public void xtestInitialCapacity_setTwice() { MapMaker maker = new MapMaker().initialCapacity(16); try { // even to the same value is not allowed maker.initialCapacity(16); fail(); } catch (IllegalArgumentException expected) { } } public void testLoadFactor_small() { MapMaker maker = new MapMaker().loadFactor(Float.MIN_VALUE); Impl map = makeCustomMap(maker); assertEquals(Float.MIN_VALUE, map.loadFactor); // has no other effect until we add an entry (which would be bad) assertEquals(1, map.segments[0].table.length()); } public void testLoadFactor_large() { MapMaker maker = new MapMaker().loadFactor(Float.MAX_VALUE); Impl map = makeCustomMap(maker); assertEquals(Float.MAX_VALUE, map.loadFactor); // these tables will never grow... we could add a ton of entries to // check that if we wanted to. assertEquals(1, map.segments[0].table.length()); } public void testLoadFactor_zero() { MapMaker maker = new MapMaker(); try { maker.loadFactor(0); fail(); } catch (IllegalArgumentException expected) { } } // TODO: enable when ready public void xtestLoadFactor_setTwice() { MapMaker maker = new MapMaker().loadFactor(0.75f); try { // even to the same value is not allowed maker.loadFactor(0.75f); fail(); } catch (IllegalArgumentException expected) { } } public void testConcurrencyLevel_small() { MapMaker maker = new MapMaker().concurrencyLevel(1); Impl map = makeCustomMap(maker); assertEquals(1, map.segments.length); } public void testConcurrencyLevel_large() { new MapMaker().concurrencyLevel(Integer.MAX_VALUE); // don't actually build this beast } public void testConcurrencyLevel_zero() { MapMaker maker = new MapMaker(); try { maker.concurrencyLevel(0); fail(); } catch (IllegalArgumentException expected) { } } // TODO: enable when ready public void xtestConcurrencyLevel_setTwice() { MapMaker maker = new MapMaker().concurrencyLevel(16); try { // even to the same value is not allowed maker.concurrencyLevel(16); fail(); } catch (IllegalArgumentException expected) { } } public void testKeyStrengthSetTwice() { MapMaker maker1 = new MapMaker().weakKeys(); try { maker1.weakKeys(); fail(); } catch (IllegalStateException expected) { } MapMaker maker2 = new MapMaker().softKeys(); try { maker2.softKeys(); fail(); } catch (IllegalStateException expected) { } MapMaker maker3 = new MapMaker().weakKeys(); try { maker3.softKeys(); fail(); } catch (IllegalStateException expected) { } } public void testValueStrengthSetTwice() { MapMaker maker1 = new MapMaker().weakValues(); try { maker1.weakValues(); fail(); } catch (IllegalStateException expected) { } MapMaker maker2 = new MapMaker().softValues(); try { maker2.softValues(); fail(); } catch (IllegalStateException expected) { } MapMaker maker3 = new MapMaker().weakValues(); try { maker3.softValues(); fail(); } catch (IllegalStateException expected) { } } public void testExpiration_small() { new MapMaker().expiration(1, NANOSECONDS); // well, it didn't blow up. } public void testExpiration_setTwice() { MapMaker maker = new MapMaker().expiration(3600, SECONDS); try { // even to the same value is not allowed maker.expiration(3600, SECONDS); fail(); } catch (IllegalStateException expected) { } } public void testReturnsPlainConcurrentHashMapWhenPossible() { Map map = new MapMaker() .concurrencyLevel(5) .loadFactor(0.5f) .initialCapacity(5) .makeMap(); assertTrue(map instanceof ConcurrentHashMap); } private static Impl makeCustomMap(MapMaker maker) { // Use makeComputingMap() to force it to return CCHM.Impl, not // ConcurrentHashMap. return (Impl) maker.makeComputingMap(new Function() { public Object apply(@Nullable Object from) { return from; } }); } } public static class RecursiveComputationTest extends TestCase { Function recursiveComputer = new Function() { public String apply(Integer key) { if (key > 0) { return key + ", " + recursiveMap.get(key - 1); } else { return "0"; } } }; ConcurrentMap recursiveMap = new MapMaker() .weakKeys() .weakValues() .makeComputingMap(recursiveComputer); public void testRecursiveComputation() { assertEquals("3, 2, 1, 0", recursiveMap.get(3)); } } /** * Tests for basic map functionality. */ public static class ReferenceMapTest extends TestCase { public void testValueCleanupWithWeakKey() { ConcurrentMap map = new MapMaker().weakKeys().makeMap(); map.put(new Object(), new Object()); assertCleanup(map); } public void testValueCleanupWithSoftKey() { ConcurrentMap map = new MapMaker().softKeys().makeMap(); map.put(new Object(), new Object()); assertCleanup(map); } public void testKeyCleanupWithWeakValue() { ConcurrentMap map = new MapMaker().weakValues().makeMap(); map.put(new Object(), new Object()); assertCleanup(map); } public void testKeyCleanupWithSoftValue() { ConcurrentMap map = new MapMaker().softValues().makeMap(); map.put(new Object(), new Object()); assertCleanup(map); } public void testInternedValueCleanupWithWeakKey() { ConcurrentMap map = new MapMaker().weakKeys().makeMap(); map.put(new Integer(5), "foo"); assertCleanup(map); } public void testInternedValueCleanupWithSoftKey() { ConcurrentMap map = new MapMaker().softKeys().makeMap(); map.put(new Integer(5), "foo"); assertCleanup(map); } public void testInternedKeyCleanupWithWeakValue() { ConcurrentMap map = new MapMaker().weakValues().makeMap(); map.put(5, new String("foo")); assertCleanup(map); } public void testInternedKeyCleanupWithSoftValue() { ConcurrentMap map = new MapMaker().softValues().makeMap(); map.put(5, new String("foo")); assertCleanup(map); } public void testReplace() { ConcurrentMap map = new MapMaker().makeMap(); assertNull(map.replace("one", 1)); } private static void assertCleanup(ConcurrentMap map) { assertEquals(1, map.size()); // wait up to 5s byte[] filler = new byte[1024]; for (int i = 0; i < 500; i++) { System.gc(); if (map.isEmpty()) { return; } try { Thread.sleep(10); } catch (InterruptedException e) { /* ignore */ } try { // Fill up heap so soft references get cleared. filler = new byte[filler.length * 2]; } catch (OutOfMemoryError e) {} } fail(); } public void testWeakKeyIdentityLookup() { ConcurrentMap map = new MapMaker().weakKeys().makeMap(); Integer key1 = new Integer(12357); Integer key2 = new Integer(12357); map.put(key1, "a"); assertTrue(map.containsKey(key1)); assertFalse(map.containsKey(key2)); } public void testSoftKeyIdentityLookup() { ConcurrentMap map = new MapMaker().softKeys().makeMap(); Integer key1 = new Integer(12357); Integer key2 = new Integer(12357); map.put(key1, "a"); assertTrue(map.containsKey(key1)); assertFalse(map.containsKey(key2)); } public void testWeakValueIdentityLookup() { ConcurrentMap map = new MapMaker().weakValues().makeMap(); Integer value1 = new Integer(12357); Integer value2 = new Integer(12357); map.put("a", value1); assertTrue(map.containsValue(value1)); assertFalse(map.containsValue(value2)); } public void testSoftValueIdentityLookup() { ConcurrentMap map = new MapMaker().softValues().makeMap(); Integer value1 = new Integer(12357); Integer value2 = new Integer(12357); map.put("a", value1); assertTrue(map.containsValue(value1)); assertFalse(map.containsValue(value2)); } public void testWeakKeyEntrySetRemove() { ConcurrentMap map = new MapMaker().weakKeys().makeMap(); Integer key1 = new Integer(12357); Integer key2 = new Integer(12357); map.put(key1, "a"); assertFalse(map.entrySet().remove(Maps.immutableEntry(key2, "a"))); assertEquals(1, map.size()); assertTrue(map.entrySet().remove(Maps.immutableEntry(key1, "a"))); assertEquals(0, map.size()); } public void testEntrySetIteratorRemove() { ConcurrentMap map = new MapMaker().makeMap(); map.put("foo", 1); map.put("bar", 2); assertEquals(2, map.size()); Iterator> iterator = map.entrySet().iterator(); try { iterator.remove(); fail(); } catch (IllegalStateException expected) {} iterator.next(); iterator.remove(); assertEquals(1, map.size()); try { iterator.remove(); fail(); } catch (IllegalStateException expected) {} iterator.next(); iterator.remove(); assertEquals(0, map.size()); } } /** * Tests for computing functionality. */ public static class ComputingTest extends TestCase { public void testComputerThatReturnsNull() { ConcurrentMap map = new MapMaker() .makeComputingMap(new Function() { public String apply(Integer key) { return null; } }); try { map.get(1); fail(); } catch (NullPointerException e) { /* expected */ } } public void testRecomputeAfterReclamation() throws InterruptedException { ConcurrentMap map = new MapMaker() .weakValues() .makeComputingMap(new Function() { @SuppressWarnings("RedundantStringConstructorCall") public String apply(Integer key) { return new String("one"); } }); for (int i = 0; i < 10; i++) { // The entry should get garbage collected and recomputed. assertEquals("on iteration " + i, "one", map.get(1)); Thread.sleep(i); System.gc(); } } public void testRuntimeException() { final RuntimeException e = new RuntimeException(); ConcurrentMap map = new MapMaker().makeComputingMap( new Function() { public Object apply(Object from) { throw e; } }); try { map.get(new Object()); fail(); } catch (ComputationException ce) { assertSame(e, ce.getCause()); } } public void testSleepConcurrency() throws InterruptedException { ConcurrentMap cache = new MapMaker() .weakKeys().weakValues().makeComputingMap(new SleepFunction()); assertConcurrency(cache, false); } public void testBusyConcurrency() throws InterruptedException { ConcurrentMap cache = new MapMaker() .weakKeys().weakValues().makeComputingMap(new BusyFunction()); assertConcurrency(cache, false); } public void testFastConcurrency() throws InterruptedException { ConcurrentMap cache = new MapMaker() .weakKeys().weakValues().makeComputingMap(new SomeFunction()); assertConcurrency(cache, false); } public void testSleepCanonical() throws InterruptedException { ConcurrentMap cache = new MapMaker() .softValues().makeComputingMap(new SleepFunction()); assertConcurrency(cache, true); } public void testBusyCanonical() throws InterruptedException { ConcurrentMap cache = new MapMaker() .softValues().makeComputingMap(new BusyFunction()); assertConcurrency(cache, true); } public void testFastCanonical() throws InterruptedException { ConcurrentMap cache = new MapMaker() .softValues().makeComputingMap(new SomeFunction()); assertConcurrency(cache, true); } private static void assertConcurrency( final ConcurrentMap cache, final boolean simulateAliasing) throws InterruptedException { final int n = 20; final CountDownLatch startSignal = new CountDownLatch(1); final CountDownLatch doneSignal = new CountDownLatch(n); for (int i = 0; i < n; i++) { new Thread() { @Override public void run() { try { startSignal.await(); for (int j = 0; j < n; j++) { cache.get(simulateAliasing ? new String("foo") : "foo"); } doneSignal.countDown(); } catch (InterruptedException ignored) {} } }.start(); } startSignal.countDown(); doneSignal.await(); assertEquals(Integer.valueOf(1), cache.get("foo")); assertEquals(Integer.valueOf(2), cache.get("bar")); } private static class SomeFunction implements Function { private int numApplies = 0; public Integer apply(String s) { return ++numApplies; } } private static class SleepFunction implements Function { private int numApplies = 0; public Integer apply(String s) { try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } return ++numApplies; } } private static class BusyFunction implements Function { private int numApplies = 0; public Integer apply(String s) { for (int i = 0; i < 1000; i++) { Math.sqrt(i); } return ++numApplies; } } } /** * Tests combinations of key and value reference types. */ public static class ReferenceCombinationTestSuite extends TestCase { interface BuilderOption { void applyTo(MapMaker maker); } public static Test suite() { TestSuite suite = new TestSuite(); BuilderOption[] keyOptions = { new BuilderOption() { public void applyTo(MapMaker maker) { // strong keys } @Override public String toString() { return "Strong"; } }, new BuilderOption() { public void applyTo(MapMaker maker) { maker.weakKeys(); } @Override public String toString() { return "Weak"; } }, new BuilderOption() { public void applyTo(MapMaker maker) { maker.softKeys(); } @Override public String toString() { return "Soft"; } }, }; BuilderOption[] valueOptions = { new BuilderOption() { public void applyTo(MapMaker maker) { // strong values } @Override public String toString() { return "Strong"; } }, new BuilderOption() { public void applyTo(MapMaker maker) { maker.weakValues(); } @Override public String toString() { return "Weak"; } }, new BuilderOption() { public void applyTo(MapMaker maker) { maker.softValues(); } @Override public String toString() { return "Soft"; } }, }; // create test cases for each key and value type. for (Method method : MapTest.class.getMethods()) { String name = method.getName(); if (name.startsWith("test")) { for (BuilderOption keyOption : keyOptions) { for (BuilderOption valueOption : valueOptions) { suite.addTest(new MapTest(name, keyOption, valueOption)); } } } } return suite; } public static class MapTest extends TestCase { final BuilderOption keyOption; final BuilderOption valueOption; public MapTest(String name, BuilderOption keyOption, BuilderOption valueOption) { super(name); this.keyOption = keyOption; this.valueOption = valueOption; } @Override public String getName() { return super.getName() + "For" + keyOption + valueOption; } MapMaker newBuilder() { MapMaker maker = new MapMaker(); keyOption.applyTo(maker); valueOption.applyTo(maker); return maker; } ConcurrentMap newMap() { MapMaker maker = new MapMaker(); keyOption.applyTo(maker); valueOption.applyTo(maker); return maker.makeMap(); } public void testContainsKey() { ConcurrentMap map = newMap(); Object k = "key"; map.put(k, "value"); assertTrue(map.containsKey(k)); } public void testClear() { ConcurrentMap map = newMap(); String k = "key"; map.put(k, "value"); assertFalse(map.isEmpty()); map.clear(); assertTrue(map.isEmpty()); assertNull(map.get(k)); } public void testKeySet() { ConcurrentMap map = newMap(); map.put("a", "foo"); map.put("b", "foo"); Set expected = set("a", "b"); assertEquals(expected, map.keySet()); } public void testValues() { ConcurrentMap map = newMap(); map.put("a", "1"); map.put("b", "2"); Set expected = set("1", "2"); Set actual = new HashSet(); actual.addAll(map.values()); assertEquals(expected, actual); } public void testPutIfAbsent() { ConcurrentMap map = newMap(); map.putIfAbsent("a", "1"); assertEquals("1", map.get("a")); map.putIfAbsent("a", "2"); assertEquals("1", map.get("a")); } public void testReplace() { ConcurrentMap map = newMap(); map.put("a", "1"); map.replace("a", "2", "2"); assertEquals("1", map.get("a")); map.replace("a", "1", "2"); assertEquals("2", map.get("a")); } public void testContainsValue() { ConcurrentMap map = newMap(); Object v = "value"; map.put("key", v); assertTrue(map.containsValue(v)); } public void testEntrySet() { final ConcurrentMap map = newMap(); map.put("a", "1"); map.put("b", "2"); @SuppressWarnings("unchecked") Set> expected = set(Maps.immutableEntry("a", "1"), Maps.immutableEntry("b", "2")); assertEquals(expected, map.entrySet()); } public void testPutAll() { ConcurrentMap map = newMap(); Object k = "key"; Object v = "value"; map.putAll(Collections.singletonMap(k, v)); assertSame(v, map.get(k)); } public void testRemove() { ConcurrentMap map = newMap(); Object k = "key"; map.put(k, "value"); map.remove(k); assertFalse(map.containsKey(k)); } public void testPutGet() { final Object k = new Object(); final Object v = new Object(); ConcurrentMap map = newMap(); map.put(k, v); assertEquals(1, map.size()); assertSame(v, map.get(k)); assertEquals(1, map.size()); assertNull(map.get(new Object())); } public void testCompute() { final Object k = new Object(); final Object v = new Object(); ConcurrentMap map = newBuilder().makeComputingMap( new Function() { public Object apply(Object key) { return key == k ? v : null; } }); assertEquals(0, map.size()); assertSame(v, map.get(k)); assertSame(v, map.get(k)); assertEquals(1, map.size()); try { map.get(new Object()); fail(); } catch (NullPointerException e) { /* expected */ } assertEquals(1, map.size()); } static class MockFunction implements Function, Serializable { int count; public Object apply(Object key) { count++; return Value.valueOf(key.toString()); } private static final long serialVersionUID = 0; } } /** * Enums conveniently maintain instance identity across serialization. */ enum Key { FOO, BAR, TEE } enum Value { FOO, BAR, TEE } } public static class ExpiringReferenceMapTest extends TestCase { private static final long EXPIRING_TIME = 10; private static final int VALUE_PREFIX = 12345; private static final String KEY_PREFIX = "key prefix:"; Timer oldTimer; final List tasks = new ArrayList(); @Override protected void setUp() throws Exception { oldTimer = ExpirationTimer.instance; ExpirationTimer.instance = new Timer() { @Override public void schedule(TimerTask task, long delay) { tasks.add(task); } }; } @Override protected void tearDown() throws Exception { ExpirationTimer.instance = oldTimer; } private void runTasks() { for (TimerTask task : tasks) { task.run(); } tasks.clear(); } public void testExpiringPut() { ConcurrentMap map = new MapMaker() .expiration(EXPIRING_TIME, TimeUnit.MILLISECONDS).makeMap(); for (int i = 0; i < 10; i++) { map.put(KEY_PREFIX + i, VALUE_PREFIX + i); assertEquals(Integer.valueOf(VALUE_PREFIX + i), map.get(KEY_PREFIX + i)); } runTasks(); assertEquals("Map must be empty by now", 0, map.size()); } public void testExpiringPutIfAbsent() { ConcurrentMap map = new MapMaker() .expiration(EXPIRING_TIME, TimeUnit.MILLISECONDS).makeMap(); for (int i = 0; i < 10; i++) { map.putIfAbsent(KEY_PREFIX + i, VALUE_PREFIX + i); assertEquals(Integer.valueOf(VALUE_PREFIX + i), map.get(KEY_PREFIX + i)); } runTasks(); assertEquals("Map must be empty by now", 0, map.size()); } public void testExpiringGetForSoft() { ConcurrentMap map = new MapMaker() .softValues().expiration(EXPIRING_TIME, TimeUnit.MILLISECONDS) .makeMap(); runExpirationTest(map); } public void testExpiringGetForStrong() { ConcurrentMap map = new MapMaker() .expiration(EXPIRING_TIME, TimeUnit.MILLISECONDS).makeMap(); runExpirationTest(map); } public void testRemovalSchedulerForStrong() { ConcurrentMap map = new MapMaker() .expiration(EXPIRING_TIME, TimeUnit.MILLISECONDS).makeMap(); runRemovalScheduler(map, KEY_PREFIX, EXPIRING_TIME); } public void testRemovalSchedulerForSoft() { ConcurrentMap map = new MapMaker() .softValues().expiration(EXPIRING_TIME, TimeUnit.MILLISECONDS) .makeMap(); runRemovalScheduler(map, KEY_PREFIX, EXPIRING_TIME); } private void runExpirationTest(ConcurrentMap map) { for (int i = 0; i < 10; i++) { map.put(KEY_PREFIX + i, VALUE_PREFIX + i); assertEquals(Integer.valueOf(VALUE_PREFIX + i), map.get(KEY_PREFIX + i)); } for (int i = 0; i < 10; i++) { assertEquals(Integer.valueOf(i + VALUE_PREFIX), map.get(KEY_PREFIX + i)); } runTasks(); for (int i = 0; i < 10; i++) { assertEquals(null, map.get(KEY_PREFIX + i)); } } private void runRemovalScheduler(ConcurrentMap map, String keyPrefix, long ttl) { int shift1 = 10 + VALUE_PREFIX; // fill with initial data for (int i = 0; i < 10; i++) { map.put(keyPrefix + i, i + shift1); assertEquals(Integer.valueOf(i + shift1), map.get(keyPrefix + i)); } // wait, so that entries have just 10 ms to live try { Thread.sleep(ttl * 2 / 3); } catch (InterruptedException e) { throw new RuntimeException(e); } int shift2 = shift1 + 10; // fill with new data - has to live for 20 ms more for (int i = 0; i < 10; i++) { map.put(keyPrefix + i, i + shift2); assertEquals("key: " + keyPrefix + i, Integer.valueOf(i + shift2), map.get(keyPrefix + i)); } // old timeouts must expire after this wait try { Thread.sleep(ttl * 2 / 3); } catch (InterruptedException e) { throw new RuntimeException(e); } // check that new values are still there - they still have 10 ms to live for (int i = 0; i < 10; i++) { assertEquals(Integer.valueOf(i + shift2), map.get(keyPrefix + i)); } } } public static class ExpiringComputingReferenceMapTest extends TestCase { static final long VERY_LONG = 100000L; static final String KEY_PREFIX = "THIS IS AN ARBITRARY KEY PREFIX"; static final int VALUE_SUFFIX = 77777; Timer oldTimer; final List tasks = new ArrayList(); @Override protected void setUp() throws Exception { oldTimer = ExpirationTimer.instance; ExpirationTimer.instance = new Timer() { @Override public void schedule(TimerTask task, long delay) { tasks.add(task); } }; } @Override protected void tearDown() throws Exception { ExpirationTimer.instance = oldTimer; } private void runTasks() { for (TimerTask task : tasks) { task.run(); } tasks.clear(); } public void testExpiringPut() { ConcurrentMap cache = new MapMaker() .expiration(50, TimeUnit.MILLISECONDS) .makeComputingMap(WATCHED_CREATOR); for (int i = 0; i < 10; i++) { cache.put(KEY_PREFIX + i, i + VALUE_SUFFIX); assertEquals(Integer.valueOf(i + VALUE_SUFFIX), cache.get(KEY_PREFIX + i)); } for (int i = 0; i < 10; i++) { WATCHED_CREATOR.reset(); assertEquals(Integer.valueOf(i + VALUE_SUFFIX), cache.get(KEY_PREFIX + i)); assertFalse("Creator should not have been called @#" + i, WATCHED_CREATOR.wasCalled()); } runTasks(); assertEquals("Cache must be empty by now", 0, cache.size()); } public void testExpiringPutIfAbsent() { ConcurrentMap cache = new MapMaker() .expiration(50, TimeUnit.MILLISECONDS) .makeComputingMap(WATCHED_CREATOR); for (int i = 0; i < 10; i++) { cache.putIfAbsent(KEY_PREFIX + i, i + VALUE_SUFFIX); assertEquals(Integer.valueOf(i + VALUE_SUFFIX), cache.get(KEY_PREFIX + i)); } runTasks(); assertEquals("Cache must be empty by now", 0, cache.size()); } public void testExpiringGetForSoft() { ConcurrentMap cache = new MapMaker() .expiration(5, TimeUnit.MILLISECONDS) .softValues().makeComputingMap(WATCHED_CREATOR); runExpirationTest(cache); } public void testExpiringGetForStrong() { ConcurrentMap cache = new MapMaker() .expiration(10, TimeUnit.MILLISECONDS) .makeComputingMap(WATCHED_CREATOR); runExpirationTest(cache); } private void runExpirationTest(ConcurrentMap cache) { for (int i = 0; i < 10; i++) { assertEquals(Integer.valueOf(i + VALUE_SUFFIX), cache.get(KEY_PREFIX + i)); } for (int i = 0; i < 10; i++) { WATCHED_CREATOR.reset(); assertEquals(Integer.valueOf(i + VALUE_SUFFIX), cache.get(KEY_PREFIX + i)); assertFalse("Creator should NOT have been called @#" + i, WATCHED_CREATOR.wasCalled()); } runTasks(); for (int i = 0; i < 10; i++) { WATCHED_CREATOR.reset(); assertEquals(Integer.valueOf(i + VALUE_SUFFIX), cache.get(KEY_PREFIX + i)); assertTrue("Creator should have been called @#" + i, WATCHED_CREATOR.wasCalled()); } } public void testRemovalSchedulerForStrong() { String keyPrefix = "TRSTRONG_"; int ttl = 300; ConcurrentMap cache = new MapMaker() .expiration(ttl, TimeUnit.MILLISECONDS) .makeComputingMap(new WatchedCreatorFunction(keyPrefix)); runRemovalScheduler(cache, keyPrefix, ttl); } public void testRemovalSchedulerForSoft() { String keyPrefix = "TRSOFT_"; int ttl = 300; ConcurrentMap cache = new MapMaker() .expiration(ttl, TimeUnit.MILLISECONDS).softValues() .makeComputingMap(new WatchedCreatorFunction(keyPrefix)); runRemovalScheduler(cache, keyPrefix, ttl); } private void runRemovalScheduler(ConcurrentMap cache, String keyPrefix, int ttl) { int shift1 = 10 + VALUE_SUFFIX; // fill with initial data for (int i = 0; i < 10; i++) { cache.put(keyPrefix + i, i + shift1); assertEquals(Integer.valueOf(i + shift1), cache.get(keyPrefix + i)); } // wait, so that entries have just 10 ms to live try { Thread.sleep(ttl * 2 / 3); } catch (InterruptedException e) { throw new RuntimeException(e); } int shift2 = shift1 + 10; // fill with new data - has to live for 20 ms more for (int i = 0; i < 10; i++) { cache.put(keyPrefix + i, i + shift2); assertEquals("key: " + keyPrefix + i, Integer.valueOf(i + shift2), cache.get(keyPrefix + i)); } // old timeouts must expire after this wait try { Thread.sleep(ttl * 2 / 3); } catch (InterruptedException e) { throw new RuntimeException(e); } // check that new values are still there - they still have 10 ms to live for (int i = 0; i < 10; i++) { assertEquals(Integer.valueOf(i + shift2), cache.get(keyPrefix + i)); } } private static class WatchedCreatorFunction implements Function { boolean wasCalled = false; // must be set in apply() public WatchedCreatorFunction() { this(KEY_PREFIX); } public WatchedCreatorFunction(String prefix) { setPrefix(prefix); } public void reset() { wasCalled = false; } protected String prefix = KEY_PREFIX; public void setPrefix(String prefix) { this.prefix = prefix; } public boolean wasCalled() { return wasCalled; } public Integer apply(String s) { wasCalled = true; return Integer.parseInt(s.substring(prefix.length())) + VALUE_SUFFIX; } } static final WatchedCreatorFunction WATCHED_CREATOR = new WatchedCreatorFunction(); } static Set set(E... elements) { return new HashSet(Arrays.asList(elements)); } } guice-3.0/core/test/com/google/inject/internal/util/FinalizableReferenceQueueTest.java0000644000175000017500000000757511461502746031145 0ustar drazzibdrazzibpackage com.google.inject.internal.util; import com.google.inject.internal.util.FinalizableReferenceQueue; import com.google.inject.internal.util.FinalizableWeakReference; import com.google.inject.internal.util.Finalizer; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.net.URL; import java.net.URLClassLoader; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class FinalizableReferenceQueueTest extends TestCase { private FinalizableReferenceQueue frq; @Override protected void tearDown() throws Exception { frq = null; } public void testFinalizeReferentCalled() { MockReference reference = new MockReference( frq = new FinalizableReferenceQueue()); // wait up to 5s for (int i = 0; i < 500; i++) { if (reference.finalizeReferentCalled) { return; } try { System.gc(); Thread.sleep(10); } catch (InterruptedException e) { /* ignore */ } } fail(); } static class MockReference extends FinalizableWeakReference { volatile boolean finalizeReferentCalled; MockReference(FinalizableReferenceQueue frq) { super(new Object(), frq); } public void finalizeReferent() { finalizeReferentCalled = true; } } /** * Keeps a weak reference to the underlying reference queue. When this * reference is cleared, we know that the background thread has stopped * and released its strong reference. */ private WeakReference> queueReference; public void testThatFinalizerStops() { weaklyReferenceQueue(); // wait up to 5s for (int i = 0; i < 500; i++) { if (queueReference.get() == null) { return; } try { System.gc(); Thread.sleep(10); } catch (InterruptedException e) { /* ignore */ } } fail(); } /** * If we don't keep a strong reference to the reference object, it won't * be enqueued. */ FinalizableWeakReference reference; /** * Create the FRQ in a method that goes out of scope so that we're sure * it will be reclaimed. */ private void weaklyReferenceQueue() { frq = new FinalizableReferenceQueue(); queueReference = new WeakReference>(frq.queue); /* * Queue and clear a reference for good measure. We test later on that * the finalizer thread stopped, but we should test that it actually * started first. */ reference = new FinalizableWeakReference(new Object(), frq) { public void finalizeReferent() { reference = null; frq = null; } }; } public void testDecoupledLoader() { FinalizableReferenceQueue.DecoupledLoader decoupledLoader = new FinalizableReferenceQueue.DecoupledLoader() { @Override URLClassLoader newLoader(URL base) { return new DecoupledClassLoader(new URL[] { base }); } }; Class finalizerCopy = decoupledLoader.loadFinalizer(); assertNotNull(finalizerCopy); assertNotSame(Finalizer.class, finalizerCopy); assertNotNull(FinalizableReferenceQueue.getStartFinalizer(finalizerCopy)); } static class DecoupledClassLoader extends URLClassLoader { public DecoupledClassLoader(URL[] urls) { super(urls); } @Override protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { // Force Finalizer to load from this class loader, not its parent. if (name.equals(Finalizer.class.getName())) { Class clazz = findClass(name); if (resolve) { resolveClass(clazz); } return clazz; } return super.loadClass(name, resolve); } } public void testGetFinalizerUrl() { assertNotNull(getClass().getResource(Finalizer.class.getSimpleName() + ".class")); } } guice-3.0/core/test/com/google/inject/internal/util/ForwardingObject.java0000644000175000017500000000565211460132770026457 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.Serializable; /** * An abstract base class for implementing the decorator pattern. * The {@link #delegate()} method must be overridden to return the instance * being decorated. * * This class does not forward the {@code hashCode} and {@code equals} * methods through to the backing object, but relies on {@code Object}'s * implementation. This is necessary to preserve the symmetry of {@code equals}. * Custom definitions of equality are usually based on an interface, such as * {@code Set} or {@code List}, so that the implementation of {@code equals} can * cast the object being tested for equality to the custom interface. {@code * ForwardingObject} implements no such custom interfaces directly; they * are implemented only in subclasses. Therefore, forwarding {@code equals} * would break symmetry, as the forwarding object might consider itself equal to * the object being tested, but the reverse could not be true. This behavior is * consistent with the JDK's collection wrappers, such as * {@link java.util.Collections#unmodifiableCollection}. Use an * interface-specific subclass of {@code ForwardingObject}, such as {@link * ForwardingList}, to preserve equality behavior, or override {@code equals} * directly. * *

The {@code toString} method is forwarded to the delegate. Although this * class does not implement {@link Serializable}, a serializable subclass may be * created since this class has a parameter-less constructor. * * @author Mike Bostock */ public abstract class ForwardingObject { /** Sole constructor. */ protected ForwardingObject() {} /** * Returns the backing delegate instance that methods are forwarded to. * Abstract subclasses generally override the {@link ForwardingObject} method * with an abstract method that has a more specific return type, such as * {@link ForwardingSet#delegate}. Concrete subclasses override this method to * supply the instance being decorated. */ protected abstract Object delegate(); /** * Returns the string representation generated by the delegate's * {@code toString} method. */ @Override public String toString() { return delegate().toString(); } /* No equals or hashCode. See class comments for details. */ } guice-3.0/core/test/com/google/inject/internal/util/ForwardingCollection.java0000644000175000017500000000514611460132770027342 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.util.Collection; import java.util.Iterator; /** * A collection which forwards all its method calls to another collection. * Subclasses should override one or more methods to modify the behavior of * the backing collection as desired per the decorator pattern. * * @see ForwardingObject * @author Kevin Bourrillion */ public abstract class ForwardingCollection extends ForwardingObject implements Collection { @Override protected abstract Collection delegate(); public Iterator iterator() { return delegate().iterator(); } public int size() { return delegate().size(); } /** * {@inheritDoc} * *

This method always throws a {@link NullPointerException} when * {@code collection} is null. */ public boolean removeAll(Collection collection) { return delegate().removeAll(checkNotNull(collection)); } public boolean isEmpty() { return delegate().isEmpty(); } public boolean contains(Object object) { return delegate().contains(object); } public Object[] toArray() { return delegate().toArray(); } public T[] toArray(T[] array) { return delegate().toArray(array); } public boolean add(E element) { return delegate().add(element); } public boolean remove(Object object) { return delegate().remove(object); } public boolean containsAll(Collection collection) { return delegate().containsAll(collection); } public boolean addAll(Collection collection) { return delegate().addAll(collection); } /** * {@inheritDoc} * *

This method always throws a {@link NullPointerException} when * {@code collection} is null. */ public boolean retainAll(Collection collection) { return delegate().retainAll(checkNotNull(collection)); } public void clear() { delegate().clear(); } } guice-3.0/core/test/com/google/inject/internal/util/LineNumbersTest.java0000644000175000017500000001136511531415310026300 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import com.google.inject.AbstractModule; import static com.google.inject.Asserts.assertContains; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.matcher.Matchers; import java.lang.reflect.Modifier; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class LineNumbersTest extends TestCase { public void testLineNumbers() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(A.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) No implementation for " + B.class.getName() + " was bound.", "for parameter 0 at " + A.class.getName() + ".(LineNumbersTest.java:", "at " + LineNumbersTest.class.getName(), ".configure(LineNumbersTest.java:"); } } static class A { @Inject A(B b) {} } public interface B {} /*if[AOP]*/ public void testCanHandleLineNumbersForGuiceGeneratedClasses() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bindInterceptor(Matchers.only(A.class), Matchers.any(), new org.aopalliance.intercept.MethodInterceptor() { public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) { return null; } }); bind(A.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) No implementation for " + B.class.getName() + " was bound.", "for parameter 0 at " + A.class.getName() + ".(LineNumbersTest.java:", "at " + LineNumbersTest.class.getName(), ".configure(LineNumbersTest.java:"); } } static class GeneratingClassLoader extends ClassLoader { static String name = "__generated"; GeneratingClassLoader() { super(B.class.getClassLoader()); } Class generate() { org.objectweb.asm.ClassWriter cw = new org.objectweb.asm.ClassWriter(org.objectweb.asm.ClassWriter.COMPUTE_MAXS); cw.visit(org.objectweb.asm.Opcodes.V1_5, Modifier.PUBLIC, name, null, org.objectweb.asm.Type.getInternalName(Object.class), null); String sig = "("+org.objectweb.asm.Type.getDescriptor(B.class)+")V"; org.objectweb.asm.MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "", sig, null, null); mv.visitAnnotation(org.objectweb.asm.Type.getDescriptor(Inject.class), true); mv.visitCode(); mv.visitVarInsn(org.objectweb.asm.Opcodes.ALOAD, 0); mv.visitMethodInsn(org.objectweb.asm.Opcodes.INVOKESPECIAL, org.objectweb.asm.Type.getInternalName(Object.class), "", "()V" ); mv.visitInsn(org.objectweb.asm.Opcodes.RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); cw.visitEnd(); byte[] buf = cw.toByteArray(); return defineClass(name.replace('/', '.'), buf, 0, buf.length); } } public void testUnavailableByteCodeShowsUnknownSource() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(new GeneratingClassLoader().generate()); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) No implementation for " + B.class.getName() + " was bound.", "for parameter 0 at " + GeneratingClassLoader.name + ".(Unknown Source)", "at " + LineNumbersTest.class.getName(), ".configure(LineNumbersTest.java:"); } } public void testGeneratedClassesCanSucceed() { final Class generated = new GeneratingClassLoader().generate(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(generated); bind(B.class).toInstance(new B() {}); } }); Object instance = injector.getInstance(generated); assertEquals(instance.getClass(), generated); } /*end[AOP]*/ } guice-3.0/core/test/com/google/inject/internal/util/ForwardingMap.java0000644000175000017500000001216211461631440025757 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Collection; import java.util.Map; import java.util.Set; /** * A map which forwards all its method calls to another map. Subclasses should * override one or more methods to modify the behavior of the backing map as * desired per the decorator pattern. * * @see ForwardingObject * @author Kevin Bourrillion * @author Jared Levy */ public abstract class ForwardingMap extends ForwardingObject implements Map { @Override protected abstract Map delegate(); public int size() { return delegate().size(); } public boolean isEmpty() { return delegate().isEmpty(); } public V remove(Object object) { return delegate().remove(object); } public void clear() { delegate().clear(); } public boolean containsKey(Object key) { return delegate().containsKey(key); } public boolean containsValue(Object value) { return delegate().containsValue(value); } public V get(Object key) { return delegate().get(key); } public V put(K key, V value) { return delegate().put(key, value); } public void putAll(Map map) { delegate().putAll(map); } private transient Set keySet; /** * {@inheritDoc} * *

The returned set's {@code removeAll} and {@code retainAll} methods * always throw a {@link NullPointerException} when given a null collection. */ public Set keySet() { return (keySet == null) ? keySet = createKeySet() : keySet; } /** * Generates a {@link Set} for use by {@link #keySet()}. * *

ForwardingMap's implementation of keySet() calls this method to * generate a collection of values, and then reuses that Set * for subsequent invocations. By default, this Set is essentially the * result of invoking keySet() on the delegate. Override this method if you * want to provide another implementation. * * @return A set for use by keySet(). */ protected Set createKeySet() { final Set delegate = delegate().keySet(); return new ForwardingSet() { @Override protected Set delegate() { return delegate; } }; } private transient Collection values; /** * {@inheritDoc} * *

The returned collection's {@code removeAll} and {@code retainAll} * methods always throw a {@link NullPointerException} when given a null * collection. */ public Collection values() { return (values == null) ? values = createValues() : values; } /** * Generates a {@link Collection} for use by {@link #values()}. * *

ForwardingMap's implementation of {@code values()} calls this method to * generate a collection of values, and then reuses that collection * for subsequent invocations. By default, this collection is essentially the * result of invoking values() on the delegate. Override this method if you * want to provide another implementation. * * @return A set for use by values(). */ protected Collection createValues() { final Collection delegate = delegate().values(); return new ForwardingCollection() { @Override protected Collection delegate() { return delegate; } }; } private transient Set> entrySet; /** * {@inheritDoc} * *

The returned set's {@code removeAll} and {@code retainAll} methods * always throw a {@link NullPointerException} when given a null collection. */ public Set> entrySet() { return (entrySet == null) ? entrySet = createEntrySet() : entrySet; } /** * Generates a {@link Set} for use by {@link #entrySet()}. * *

ForwardingMap's implementation of entrySet() calls this method to * generate a set of entries, and then reuses that set for subsequent * invocations. By default, this set is essentially the result of invoking * entrySet() on the delegate. Override this method if you want to * provide another implementation. * * @return A set for use by entrySet(). */ protected Set> createEntrySet() { final Set> delegate = delegate().entrySet(); return new ForwardingSet>() { @Override protected Set> delegate() { return delegate; } }; } @Override public boolean equals(@Nullable Object object) { return object == this || delegate().equals(object); } @Override public int hashCode() { return delegate().hashCode(); } } guice-3.0/core/test/com/google/inject/internal/util/Jsr166HashMap.java0000644000175000017500000001505611460132770025462 0ustar drazzibdrazzib/* * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at * http://creativecommons.org/licenses/publicdomain * Other contributors include Andrew Wright, Jeffrey Hayes, * Pat Fisher, Mike Judd. */ package com.google.inject.internal.util; import com.google.inject.internal.util.ForwardingConcurrentMap; import com.google.inject.internal.util.CustomConcurrentHashMap; import java.io.Serializable; import java.util.Map; import java.util.concurrent.ConcurrentMap; /** * A copy of {@link java.util.concurrent.ConcurrentHashMap} used to test {@link * com.google.inject.internal.util.CustomConcurrentHashMap}. This also serves * as the examples in the CustomConcurrentHashMap Javadocs. */ public class Jsr166HashMap extends ForwardingConcurrentMap implements Serializable { static class ConcurrentHashMapStrategy implements CustomConcurrentHashMap.Strategy>, Serializable { public InternalEntry newEntry(K key, int hash, InternalEntry next) { return new InternalEntry(key, hash, null, next); } public InternalEntry copyEntry(K key, InternalEntry original, InternalEntry next) { return new InternalEntry(key, original.hash, original.value, next); } public void setValue(InternalEntry entry, V value) { entry.value = value; } public V getValue(InternalEntry entry) { return entry.value; } public boolean equalKeys(K a, Object b) { return a.equals(b); } public boolean equalValues(V a, Object b) { return a.equals(b); } public int hashKey(Object key) { return key.hashCode(); } public K getKey(InternalEntry entry) { return entry.key; } public InternalEntry getNext(InternalEntry entry) { return entry.next; } public int getHash(InternalEntry entry) { return entry.hash; } public void setInternals(CustomConcurrentHashMap.Internals> internals) {} // ignored } static class InternalEntry { final K key; final int hash; final InternalEntry next; volatile V value; InternalEntry(K key, int hash, V value, InternalEntry next) { this.key = key; this.hash = hash; this.value = value; this.next = next; } } /* ---------------- Public operations -------------- */ /** * The default initial capacity for this table, * used when not otherwise specified in a constructor. */ static final int DEFAULT_INITIAL_CAPACITY = 16; /** * The default load factor for this table, used when not * otherwise specified in a constructor. */ static final float DEFAULT_LOAD_FACTOR = 0.75f; /** * The default concurrency level for this table, used when not * otherwise specified in a constructor. */ static final int DEFAULT_CONCURRENCY_LEVEL = 16; final ConcurrentMap delegate; protected ConcurrentMap delegate() { return delegate; } /** * Creates a new, empty map with the specified initial capacity, load factor * and concurrency level. * * @param initialCapacity the initial capacity. The implementation performs * internal sizing to accommodate this many * elements. * @param loadFactor the load factor threshold, used to control * resizing. Resizing may be performed when the * average number of elements per bin exceeds this * threshold. * @param concurrencyLevel the estimated number of concurrently updating * threads. The implementation performs internal * sizing to try to accommodate this many threads. * @throws IllegalArgumentException if the initial capacity is negative or * the load factor or concurrencyLevel are * nonpositive. */ public Jsr166HashMap(int initialCapacity, float loadFactor, int concurrencyLevel) { this.delegate = new CustomConcurrentHashMap.Builder() .initialCapacity(initialCapacity) .loadFactor(loadFactor) .concurrencyLevel(concurrencyLevel) .buildMap(new ConcurrentHashMapStrategy()); } /** * Creates a new, empty map with the specified initial capacity and load * factor and with the default concurrencyLevel (16). * * @param initialCapacity The implementation performs internal sizing to * accommodate this many elements. * @param loadFactor the load factor threshold, used to control * resizing. Resizing may be performed when the * average number of elements per bin exceeds this * threshold. * @throws IllegalArgumentException if the initial capacity of elements is * negative or the load factor is * nonpositive * @since 1.6 */ public Jsr166HashMap(int initialCapacity, float loadFactor) { this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL); } /** * Creates a new, empty map with the specified initial capacity, and with * default load factor (0.75) and concurrencyLevel (16). * * @param initialCapacity the initial capacity. The implementation performs * internal sizing to accommodate this many * elements. * @throws IllegalArgumentException if the initial capacity of elements is * negative. */ public Jsr166HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL); } /** * Creates a new, empty map with a default initial capacity (16), load * factor (0.75) and concurrencyLevel (16). */ public Jsr166HashMap() { this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL); } /** * Creates a new map with the same mappings as the given map. The map is * created with a capacity of 1.5 times the number of mappings in the given * map or 16 (whichever is greater), and a default load factor (0.75) and * concurrencyLevel (16). * * @param m the map */ public Jsr166HashMap(Map m) { this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL); putAll(m); } }guice-3.0/core/test/com/google/inject/internal/util/ForwardingSet.java0000644000175000017500000000246211461631440025777 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Set; /** * A set which forwards all its method calls to another set. Subclasses should * override one or more methods to modify the behavior of the backing set as * desired per the decorator pattern. * * @see ForwardingObject * @author Kevin Bourrillion */ public abstract class ForwardingSet extends ForwardingCollection implements Set { @Override protected abstract Set delegate(); @Override public boolean equals(@Nullable Object object) { return object == this || delegate().equals(object); } @Override public int hashCode() { return delegate().hashCode(); } } guice-3.0/core/test/com/google/inject/BindingTest.java0000644000175000017500000003735711460132772022660 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Sets; import com.google.inject.matcher.Matchers; import static com.google.inject.name.Names.named; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeListener; import java.lang.reflect.Constructor; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Logger; import junit.framework.TestCase; /*if[AOP]*/ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /*end[AOP]*/ /** * @author crazybob@google.com (Bob Lee) */ public class BindingTest extends TestCase { static class Dependent { @Inject A a; @Inject Dependent(A a, B b) {} @Inject void injectBob(Bob bob) {} } public void testExplicitCyclicDependency() { Guice.createInjector(new AbstractModule() { protected void configure() { bind(A.class); bind(B.class); } }).getInstance(A.class); } static class A { @Inject B b; } static class B { @Inject A a; } static class Bob {} static class MyModule extends AbstractModule { protected void configure() { // Linked. bind(Object.class).to(Runnable.class).in(Scopes.SINGLETON); // Instance. bind(Runnable.class).toInstance(new Runnable() { public void run() {} }); // Provider instance. bind(Foo.class).toProvider(new Provider() { public Foo get() { return new Foo(); } }).in(Scopes.SINGLETON); // Provider. bind(Foo.class) .annotatedWith(named("provider")) .toProvider(FooProvider.class); // Class. bind(Bar.class).in(Scopes.SINGLETON); // Constant. bindConstant().annotatedWith(named("name")).to("Bob"); } } static class Foo {} public static class FooProvider implements Provider { public Foo get() { throw new UnsupportedOperationException(); } } public static class Bar {} public void testBindToUnboundLinkedBinding() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(Collection.class).to(List.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "No implementation for java.util.List was bound."); } } /** * This test ensures that the asEagerSingleton() scoping applies to the key, * not to what the key is linked to. */ public void testScopeIsAppliedToKeyNotTarget() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Integer.class).toProvider(Counter.class).asEagerSingleton(); bind(Number.class).toProvider(Counter.class).asEagerSingleton(); } }); assertNotSame(injector.getInstance(Integer.class), injector.getInstance(Number.class)); } static class Counter implements Provider { static AtomicInteger next = new AtomicInteger(1); public Integer get() { return next.getAndIncrement(); } } public void testAnnotatedNoArgConstructor() { assertBindingSucceeds(PublicNoArgAnnotated.class); assertBindingSucceeds(ProtectedNoArgAnnotated.class); assertBindingSucceeds(PackagePrivateNoArgAnnotated.class); assertBindingSucceeds(PrivateNoArgAnnotated.class); } static class PublicNoArgAnnotated { @Inject public PublicNoArgAnnotated() { } } static class ProtectedNoArgAnnotated { @Inject protected ProtectedNoArgAnnotated() { } } static class PackagePrivateNoArgAnnotated { @Inject PackagePrivateNoArgAnnotated() { } } static class PrivateNoArgAnnotated { @Inject private PrivateNoArgAnnotated() { } } public void testUnannotatedNoArgConstructor() throws Exception{ assertBindingSucceeds(PublicNoArg.class); assertBindingSucceeds(ProtectedNoArg.class); assertBindingSucceeds(PackagePrivateNoArg.class); assertBindingSucceeds(PrivateNoArgInPrivateClass.class); assertBindingFails(PrivateNoArg.class); } static class PublicNoArg { public PublicNoArg() { } } static class ProtectedNoArg { protected ProtectedNoArg() { } } static class PackagePrivateNoArg { PackagePrivateNoArg() { } } private static class PrivateNoArgInPrivateClass { PrivateNoArgInPrivateClass() { } } static class PrivateNoArg { private PrivateNoArg() { } } private void assertBindingSucceeds(final Class clazz) { assertNotNull(Guice.createInjector().getInstance(clazz)); } private void assertBindingFails(final Class clazz) throws NoSuchMethodException { try { Guice.createInjector().getInstance(clazz); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "Could not find a suitable constructor in " + PrivateNoArg.class.getName(), "at " + PrivateNoArg.class.getName() + ".class(BindingTest.java:"); } } public void testTooManyConstructors() { try { Guice.createInjector().getInstance(TooManyConstructors.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), TooManyConstructors.class.getName() + " has more than one constructor annotated with " + "@Inject. Classes must have either one (and only one) constructor", "at " + TooManyConstructors.class.getName() + ".class(BindingTest.java:"); } } static class TooManyConstructors { @Inject TooManyConstructors(Injector i) {} @Inject TooManyConstructors() {} } public void testToConstructorBinding() throws NoSuchMethodException { final Constructor constructor = D.class.getConstructor(Stage.class); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Object.class).toConstructor(constructor); } }); D d = (D) injector.getInstance(Object.class); assertEquals(Stage.DEVELOPMENT, d.stage); } public void testToConstructorBindingsOnParameterizedTypes() throws NoSuchMethodException { final Constructor constructor = C.class.getConstructor(Stage.class, Object.class); final Key s = new Key(named("s")) {}; final Key i = new Key(named("i")) {}; Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(s).toConstructor(constructor, new TypeLiteral>() {}); bind(i).toConstructor(constructor, new TypeLiteral>() {}); } }); C one = (C) injector.getInstance(s); assertEquals(Stage.DEVELOPMENT, one.stage); assertEquals(Stage.DEVELOPMENT, one.t); assertEquals(Stage.DEVELOPMENT, one.anotherT); C two = (C) injector.getInstance(i); assertEquals(Stage.DEVELOPMENT, two.stage); assertEquals(injector, two.t); assertEquals(injector, two.anotherT); } public void testToConstructorBindingsFailsOnRawTypes() throws NoSuchMethodException { final Constructor constructor = C.class.getConstructor(Stage.class, Object.class); try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(Object.class).toConstructor(constructor); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) T cannot be used as a key; It is not fully specified.", "at " + C.class.getName() + ".(BindingTest.java:", "2) T cannot be used as a key; It is not fully specified.", "at " + C.class.getName() + ".anotherT(BindingTest.java:"); } } /*if[AOP]*/ public void testToConstructorAndMethodInterceptors() throws NoSuchMethodException { final Constructor constructor = D.class.getConstructor(Stage.class); final AtomicInteger count = new AtomicInteger(); final MethodInterceptor countingInterceptor = new MethodInterceptor() { public Object invoke(MethodInvocation methodInvocation) throws Throwable { count.incrementAndGet(); return methodInvocation.proceed(); } }; Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Object.class).toConstructor(constructor); bindInterceptor(Matchers.any(), Matchers.any(), countingInterceptor); } }); D d = (D) injector.getInstance(Object.class); d.hashCode(); d.hashCode(); assertEquals(2, count.get()); } /*end[AOP]*/ public void testInaccessibleConstructor() throws NoSuchMethodException { final Constructor constructor = E.class.getDeclaredConstructor(Stage.class); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(E.class).toConstructor(constructor); } }); E e = injector.getInstance(E.class); assertEquals(Stage.DEVELOPMENT, e.stage); } public void testToConstructorAndScopes() throws NoSuchMethodException { final Constructor constructor = F.class.getConstructor(Stage.class); final Key d = Key.get(Object.class, named("D")); // default scoping final Key s = Key.get(Object.class, named("S")); // singleton final Key n = Key.get(Object.class, named("N")); // "N" instances final Key r = Key.get(Object.class, named("R")); // a regular binding Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(d).toConstructor(constructor); bind(s).toConstructor(constructor).in(Singleton.class); bind(n).toConstructor(constructor).in(Scopes.NO_SCOPE); bind(r).to(F.class); } }); assertDistinct(injector, 1, d, d, d, d); assertDistinct(injector, 1, s, s, s, s); assertDistinct(injector, 4, n, n, n, n); assertDistinct(injector, 1, r, r, r, r); assertDistinct(injector, 4, d, d, r, r, s, s, n); } public void assertDistinct(Injector injector, int expectedCount, Key... keys) { ImmutableSet.Builder builder = ImmutableSet.builder(); for (Key k : keys) { builder.add(injector.getInstance(k)); } assertEquals(expectedCount, builder.build().size()); } public void testToConstructorSpiData() throws NoSuchMethodException { final Set> heardTypes = Sets.newHashSet(); final Constructor constructor = D.class.getConstructor(Stage.class); final TypeListener listener = new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { if (!heardTypes.add(type)) { fail("Heard " + type + " multiple times!"); } } }; Guice.createInjector(new AbstractModule() { protected void configure() { bind(Object.class).toConstructor(constructor); bind(D.class).toConstructor(constructor); bindListener(Matchers.any(), listener); } }); assertEquals(ImmutableSet.of(TypeLiteral.get(Stage.class), TypeLiteral.get(D.class)), heardTypes); } public void testInterfaceToImplementationConstructor() throws NoSuchMethodException { final Constructor constructor = CFoo.class.getDeclaredConstructor(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(IFoo.class).toConstructor(constructor); } }); injector.getInstance(IFoo.class); } public static interface IFoo {} public static class CFoo implements IFoo {} public void testGetAllBindings() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(D.class).toInstance(new D(Stage.PRODUCTION)); bind(Object.class).to(D.class); getProvider(new Key>() {}); } }); Map,Binding> bindings = injector.getAllBindings(); assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class), Key.get(Logger.class), Key.get(Object.class), new Key>() {}), bindings.keySet()); // add a JIT binding injector.getInstance(F.class); Map,Binding> bindings2 = injector.getAllBindings(); assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class), Key.get(Logger.class), Key.get(Object.class), new Key>() {}, Key.get(F.class)), bindings2.keySet()); // the original map shouldn't have changed assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class), Key.get(Logger.class), Key.get(Object.class), new Key>() {}), bindings.keySet()); // check the bindings' values assertEquals(injector, bindings.get(Key.get(Injector.class)).getProvider().get()); } public void testGetAllServletBindings() throws Exception { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(F.class); // an explicit binding that uses a JIT binding for a constructor } }); injector.getAllBindings(); } public static class C { private Stage stage; private T t; @Inject T anotherT; public C(Stage stage, T t) { this.stage = stage; this.t = t; } @Inject C() {} } public static class D { Stage stage; public D(Stage stage) { this.stage = stage; } } private static class E { Stage stage; private E(Stage stage) { this.stage = stage; } } @Singleton public static class F { Stage stage; @Inject public F(Stage stage) { this.stage = stage; } } public void testTurkeyBaconProblemUsingToConstuctor() { Injector injector = Guice.createInjector(new AbstractModule() { @SuppressWarnings("unchecked") @Override public void configure() { bind(Bacon.class).to(UncookedBacon.class); bind(Bacon.class).annotatedWith(named("Turkey")).to(TurkeyBacon.class); bind(Bacon.class).annotatedWith(named("Cooked")).toConstructor( (Constructor)InjectionPoint.forConstructorOf(Bacon.class).getMember()); } }); Bacon bacon = injector.getInstance(Bacon.class); assertEquals(Food.PORK, bacon.getMaterial()); assertFalse(bacon.isCooked()); Bacon turkeyBacon = injector.getInstance(Key.get(Bacon.class, named("Turkey"))); assertEquals(Food.TURKEY, turkeyBacon.getMaterial()); assertTrue(turkeyBacon.isCooked()); Bacon cookedBacon = injector.getInstance(Key.get(Bacon.class, named("Cooked"))); assertEquals(Food.PORK, cookedBacon.getMaterial()); assertTrue(cookedBacon.isCooked()); } enum Food { TURKEY, PORK } private static class Bacon { public Food getMaterial() { return Food.PORK; } public boolean isCooked() { return true; } } private static class TurkeyBacon extends Bacon { public Food getMaterial() { return Food.TURKEY; } } private static class UncookedBacon extends Bacon { public boolean isCooked() { return false; } } } guice-3.0/core/test/com/google/inject/ImplicitBindingTest.java0000644000175000017500000002245211460132772024341 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.internal.util.Iterables; import java.util.List; import com.google.inject.name.Named; import com.google.inject.name.Names; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class ImplicitBindingTest extends TestCase { public void testCircularDependency() throws CreationException { Injector injector = Guice.createInjector(); Foo foo = injector.getInstance(Foo.class); assertSame(foo, foo.bar.foo); } static class Foo { @Inject Bar bar; } static class Bar { final Foo foo; @Inject public Bar(Foo foo) { this.foo = foo; } } public void testDefaultImplementation() { Injector injector = Guice.createInjector(); I i = injector.getInstance(I.class); i.go(); } @ImplementedBy(IImpl.class) interface I { void go(); } static class IImpl implements I { public void go() {} } static class AlternateImpl implements I { public void go() {} } public void testDefaultProvider() { Injector injector = Guice.createInjector(); Provided provided = injector.getInstance(Provided.class); provided.go(); } public void testBindingOverridesImplementedBy() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(I.class).to(AlternateImpl.class); } }); assertEquals(AlternateImpl.class, injector.getInstance(I.class).getClass()); } @ProvidedBy(ProvidedProvider.class) interface Provided { void go(); } public void testNoImplicitBindingIsCreatedForAnnotatedKeys() { try { Guice.createInjector().getInstance(Key.get(I.class, Names.named("i"))); fail(); } catch (ConfigurationException expected) { Asserts.assertContains(expected.getMessage(), "1) No implementation for " + I.class.getName(), "annotated with @" + Named.class.getName() + "(value=i) was bound.", "while locating " + I.class.getName(), " annotated with @" + Named.class.getName() + "(value=i)"); } } static class ProvidedProvider implements Provider { public Provided get() { return new Provided() { public void go() {} }; } } /** * When we're building the binding for A, we temporarily insert that binding to support circular * dependencies. And so we can successfully create a binding for B. But later, when the binding * for A ultimately fails, we need to clean up the dependent binding for B. * * The test loops through linked bindings & bindings with constructor & member injections, * to make sure that all are cleaned up and traversed. It also makes sure we don't touch * explicit bindings. */ public void testCircularJitBindingsLeaveNoResidue() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Valid.class); bind(Valid2.class); } }); // Capture good bindings. Binding v1 = injector.getBinding(Valid.class); Binding v2 = injector.getBinding(Valid2.class); Binding jv1 = injector.getBinding(JitValid.class); Binding jv2 = injector.getBinding(JitValid2.class); // Then validate that a whole series of invalid bindings are erased. assertFailure(injector, Invalid.class); assertFailure(injector, InvalidLinked.class); assertFailure(injector, InvalidLinkedImpl.class); assertFailure(injector, InvalidLinked2.class); assertFailure(injector, InvalidLinked2Impl.class); assertFailure(injector, InvalidProvidedBy.class); assertFailure(injector, InvalidProvidedByProvider.class); assertFailure(injector, InvalidProvidedBy2.class); assertFailure(injector, InvalidProvidedBy2Provider.class); assertFailure(injector, Invalid2.class); // Validate we didn't do anything to the valid explicit bindings. assertSame(v1, injector.getBinding(Valid.class)); assertSame(v2, injector.getBinding(Valid2.class)); // Validate that we didn't erase the valid JIT bindings assertSame(jv1, injector.getBinding(JitValid.class)); assertSame(jv2, injector.getBinding(JitValid2.class)); } @SuppressWarnings("unchecked") private void assertFailure(Injector injector, Class clazz) { try { injector.getBinding(clazz); fail("Shouldn't have been able to get binding of: " + clazz); } catch(ConfigurationException expected) { List sources = Iterables.getOnlyElement(expected.getErrorMessages()).getSources(); // Assert that the first item in the sources if the key for the class we're looking up, // ensuring that each lookup is "new". assertEquals(Key.get(clazz).toString(), sources.get(0).toString()); // Assert that the last item in each lookup contains the InvalidInterface class Asserts.assertContains(sources.get(sources.size()-1).toString(), Key.get(InvalidInterface.class).toString()); } } static class Invalid { @Inject Valid a; @Inject JitValid b; @Inject InvalidProvidedBy c; @Inject Invalid(InvalidLinked a) {} @Inject void foo(InvalidInterface a) {} } @ImplementedBy(InvalidLinkedImpl.class) static interface InvalidLinked {} static class InvalidLinkedImpl implements InvalidLinked { @Inject InvalidLinked2 a; } @ImplementedBy(InvalidLinked2Impl.class) static interface InvalidLinked2 {} static class InvalidLinked2Impl implements InvalidLinked2 { @Inject InvalidLinked2Impl(Invalid2 a) {} } @ProvidedBy(InvalidProvidedByProvider.class) static interface InvalidProvidedBy {} static class InvalidProvidedByProvider implements Provider { @Inject InvalidProvidedBy2 a; public InvalidProvidedBy get() { return null; } } @ProvidedBy(InvalidProvidedBy2Provider.class) static interface InvalidProvidedBy2 {} static class InvalidProvidedBy2Provider implements Provider { @Inject Invalid2 a; public InvalidProvidedBy2 get() { return null; } } static class Invalid2 { @Inject Invalid a; } interface InvalidInterface {} static class Valid { @Inject Valid2 a; } static class Valid2 {} static class JitValid { @Inject JitValid2 a; } static class JitValid2 {} /** * Regression test for http://code.google.com/p/google-guice/issues/detail?id=319 * * The bug is that a class that asks for a provider for itself during injection time, * where any one of the other types required to fulfill the object creation was bound * in a child constructor, explodes when the injected Provider is called. * * It works just fine when the other types are bound in a main injector. */ public void testInstancesRequestingProvidersForThemselvesWithChildInjectors() { final Module testModule = new AbstractModule() { @Override protected void configure() { bind(String.class) .toProvider(TestStringProvider.class); } }; // Verify it works when the type is setup in the parent. Injector parentSetupRootInjector = Guice.createInjector(testModule); Injector parentSetupChildInjector = parentSetupRootInjector.createChildInjector(); assertEquals(TestStringProvider.TEST_VALUE, parentSetupChildInjector.getInstance( RequiresProviderForSelfWithOtherType.class).getValue()); // Verify it works when the type is setup in the child, not the parent. // If it still occurs, the bug will explode here. Injector childSetupRootInjector = Guice.createInjector(); Injector childSetupChildInjector = childSetupRootInjector.createChildInjector(testModule); assertEquals(TestStringProvider.TEST_VALUE, childSetupChildInjector.getInstance( RequiresProviderForSelfWithOtherType.class).getValue()); } static class TestStringProvider implements Provider { static final String TEST_VALUE = "This is to verify it all works"; public String get() { return TEST_VALUE; } } static class RequiresProviderForSelfWithOtherType { private final Provider selfProvider; private final String providedStringValue; @Inject RequiresProviderForSelfWithOtherType( String providedStringValue, Provider selfProvider ) { this.providedStringValue = providedStringValue; this.selfProvider = selfProvider; } public String getValue() { // Attempt to get another instance of ourself. This pattern // is possible for recursive processing. selfProvider.get(); return providedStringValue; } } } guice-3.0/core/test/com/google/inject/BindingAnnotationTest.java0000644000175000017500000000502611460132772024677 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class BindingAnnotationTest extends TestCase { public void testAnnotationWithValueMatchesKeyWithTypeOnly() throws CreationException { Injector c = Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(Blue.class).to("foo"); bind(Foo.class); } }); Foo foo = c.getInstance(Foo.class); assertEquals("foo", foo.s); } public void testAnnotationWithValueThatDoesntMatch() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(createBlue(6)).to("six"); bind(String.class).toInstance("bar"); bind(Foo.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "No implementation for java.lang.String annotated with", "BindingAnnotationTest$Blue(value=5) was bound", "at " + BindingAnnotationTest.class.getName(), ".configure(BindingAnnotationTest.java:"); } } static class Foo { @Inject @Blue(5) String s; } @Retention(RUNTIME) @BindingAnnotation @interface Blue { int value(); } public Blue createBlue(final int value) { return new Blue() { public int value() { return value; } public Class annotationType() { return Blue.class; } @Override public boolean equals(Object o) { return o instanceof Blue && ((Blue) o).value() == value; } @Override public int hashCode() { return 127 * "value".hashCode() ^ value; } }; } } guice-3.0/core/test/com/google/inject/BoundProviderTest.java0000644000175000017500000000452211460132772024054 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class BoundProviderTest extends TestCase { public void testFooProvider() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class).toProvider(FooProvider.class); } }); Foo a = injector.getInstance(Foo.class); Foo b = injector.getInstance(Foo.class); assertEquals(0, a.i); assertEquals(0, b.i); assertNotNull(a.bar); assertNotNull(b.bar); assertNotSame(a.bar, b.bar); } public void testSingletonFooProvider() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class).toProvider(SingletonFooProvider.class); } }); Foo a = injector.getInstance(Foo.class); Foo b = injector.getInstance(Foo.class); assertEquals(0, a.i); assertEquals(1, b.i); assertNotNull(a.bar); assertNotNull(b.bar); assertSame(a.bar, b.bar); } static class Bar {} static class Foo { final Bar bar; final int i; Foo(Bar bar, int i) { this.bar = bar; this.i = i; } } static class FooProvider implements Provider { final Bar bar; int count = 0; @Inject public FooProvider(Bar bar) { this.bar = bar; } public Foo get() { return new Foo(this.bar, count++); } } @Singleton static class SingletonFooProvider implements Provider { final Bar bar; int count = 0; @Inject public SingletonFooProvider(Bar bar) { this.bar = bar; } public Foo get() { return new Foo(this.bar, count++); } } } guice-3.0/core/test/com/google/inject/ProvisionExceptionTest.java0000644000175000017500000002714111530444606025143 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import static com.google.inject.Asserts.reserialize; import java.io.IOException; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ @SuppressWarnings("UnusedDeclaration") public class ProvisionExceptionTest extends TestCase { public void testExceptionsCollapsed() { try { Guice.createInjector().getInstance(A.class); fail(); } catch (ProvisionException e) { assertTrue(e.getCause() instanceof UnsupportedOperationException); assertContains(e.getMessage(), "Error injecting constructor", "for parameter 0 at com.google.inject.ProvisionExceptionTest$C.setD", "for field at com.google.inject.ProvisionExceptionTest$B.c", "for parameter 0 at com.google.inject.ProvisionExceptionTest$A"); } } /** * There's a pass-through of user code in the scope. We want exceptions thrown by Guice to be * limited to a single exception, even if it passes through user code. */ public void testExceptionsCollapsedWithScopes() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(B.class).in(Scopes.SINGLETON); } }).getInstance(A.class); fail(); } catch (ProvisionException e) { assertTrue(e.getCause() instanceof UnsupportedOperationException); assertFalse(e.getMessage().contains("custom provider")); assertContains(e.getMessage(), "Error injecting constructor", "for parameter 0 at com.google.inject.ProvisionExceptionTest$C.setD", "for field at com.google.inject.ProvisionExceptionTest$B.c", "for parameter 0 at com.google.inject.ProvisionExceptionTest$A"); } } public void testMethodInjectionExceptions() { try { Guice.createInjector().getInstance(E.class); fail(); } catch (ProvisionException e) { assertTrue(e.getCause() instanceof UnsupportedOperationException); assertContains(e.getMessage(), "Error injecting method", "at " + E.class.getName() + ".setObject(ProvisionExceptionTest.java:"); } } public void testBindToProviderInstanceExceptions() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(D.class).toProvider(new DProvider()); } }).getInstance(D.class); fail(); } catch (ProvisionException e) { assertTrue(e.getCause() instanceof UnsupportedOperationException); assertContains(e.getMessage(), "1) Error in custom provider, java.lang.UnsupportedOperationException", "at " + ProvisionExceptionTest.class.getName(), ".configure(ProvisionExceptionTest.java"); } } /** * This test demonstrates that if the user throws a ProvisionException, we wrap it to add context. */ public void testProvisionExceptionsAreWrappedForBindToType() { try { Guice.createInjector().getInstance(F.class); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "1) User Exception", "at " + F.class.getName() + ".(ProvisionExceptionTest.java:"); } } public void testProvisionExceptionsAreWrappedForBindToProviderType() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(F.class).toProvider(FProvider.class); } }).getInstance(F.class); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "1) User Exception", "while locating ", FProvider.class.getName(), "while locating ", F.class.getName()); } } public void testProvisionExceptionsAreWrappedForBindToProviderInstance() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(F.class).toProvider(new FProvider()); } }).getInstance(F.class); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "1) User Exception", "at " + ProvisionExceptionTest.class.getName(), ".configure(ProvisionExceptionTest.java"); } } public void testProvisionExceptionIsSerializable() throws IOException { try { Guice.createInjector().getInstance(A.class); fail(); } catch (ProvisionException expected) { ProvisionException reserialized = reserialize(expected); assertContains(reserialized.getMessage(), "1) Error injecting constructor, java.lang.UnsupportedOperationException", "at com.google.inject.ProvisionExceptionTest$RealD.()", "at Key[type=com.google.inject.ProvisionExceptionTest$RealD, annotation=[none]]", "@com.google.inject.ProvisionExceptionTest$C.setD()[0]", "at Key[type=com.google.inject.ProvisionExceptionTest$C, annotation=[none]]", "@com.google.inject.ProvisionExceptionTest$B.c", "at Key[type=com.google.inject.ProvisionExceptionTest$B, annotation=[none]]", "@com.google.inject.ProvisionExceptionTest$A.()[0]", "at Key[type=com.google.inject.ProvisionExceptionTest$A, annotation=[none]]"); } } public void testMultipleCauses() { try { Guice.createInjector().getInstance(G.class); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "1) Error injecting method, java.lang.IllegalArgumentException", "Caused by: java.lang.IllegalArgumentException: java.lang.UnsupportedOperationException", "Caused by: java.lang.UnsupportedOperationException: Unsupported", "2) Error injecting method, java.lang.NullPointerException: can't inject second either", "Caused by: java.lang.NullPointerException: can't inject second either", "2 errors"); } } public void testInjectInnerClass() throws Exception { Injector injector = Guice.createInjector(); try { injector.getInstance(InnerClass.class); fail(); } catch (Exception expected) { assertContains(expected.getMessage(), "Injecting into inner classes is not supported.", "while locating " + InnerClass.class.getName()); } } public void testInjectLocalClass() throws Exception { class LocalClass {} Injector injector = Guice.createInjector(); try { injector.getInstance(LocalClass.class); fail(); } catch (Exception expected) { assertContains(expected.getMessage(), "Injecting into inner classes is not supported.", "while locating " + LocalClass.class.getName()); } } public void testBindingAnnotationsOnMethodsAndConstructors() { try { Injector injector = Guice.createInjector(); injector.getInstance(MethodWithBindingAnnotation.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), MethodWithBindingAnnotation.class.getName() + ".injectMe() is annotated with @", Green.class.getName() + "(), ", "but binding annotations should be applied to its parameters instead.", "while locating " + MethodWithBindingAnnotation.class.getName()); } try { Guice.createInjector().getInstance(ConstructorWithBindingAnnotation.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), ConstructorWithBindingAnnotation.class.getName() + ".() is annotated with @", Green.class.getName() + "(), ", "but binding annotations should be applied to its parameters instead.", "at " + ConstructorWithBindingAnnotation.class.getName() + ".class", "while locating " + ConstructorWithBindingAnnotation.class.getName()); } } public void testBindingAnnotationWarningForScala() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).annotatedWith(Green.class).toInstance("lime!"); } }); injector.getInstance(LikeScala.class); } public void testLinkedBindings() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(D.class).to(RealD.class); } }); try { injector.getInstance(D.class); fail(); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "at " + RealD.class.getName() + ".(ProvisionExceptionTest.java:", "while locating " + RealD.class.getName(), "while locating " + D.class.getName()); } } public void testProviderKeyBindings() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(D.class).toProvider(DProvider.class); } }); try { injector.getInstance(D.class); fail(); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "while locating " + DProvider.class.getName(), "while locating " + D.class.getName()); } } private class InnerClass {} static class A { @Inject A(B b) { } } static class B { @Inject C c; } static class C { @Inject void setD(RealD d) { } } static class E { @Inject void setObject(Object o) { throw new UnsupportedOperationException(); } } static class MethodWithBindingAnnotation { @Inject @Green void injectMe(String greenString) {} } static class ConstructorWithBindingAnnotation { @Inject @Green ConstructorWithBindingAnnotation(String greenString) {} } /** * In Scala, fields automatically get accessor methods with the same name. So we don't do * misplaced-binding annotation detection if the offending method has a matching field. */ static class LikeScala { @Inject @Green String green; @Inject @Green String green() { return green; } } @Retention(RUNTIME) @Target({ FIELD, PARAMETER, CONSTRUCTOR, METHOD }) @BindingAnnotation @interface Green {} interface D {} static class RealD implements D { @Inject RealD() { throw new UnsupportedOperationException(); } } static class DProvider implements Provider { public D get() { throw new UnsupportedOperationException(); } } static class F { @Inject public F() { throw new ProvisionException("User Exception", new RuntimeException()); } } static class FProvider implements Provider { public F get() { return new F(); } } static class G { @Inject void injectFirst() { throw new IllegalArgumentException(new UnsupportedOperationException("Unsupported")); } @Inject void injectSecond() { throw new NullPointerException("can't inject second either"); } } } guice-3.0/core/test/com/google/inject/BinderTestSuite.java0000644000175000017500000005704011460132772023512 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.binder.ScopedBindingBuilder; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Lists; import com.google.inject.name.Named; import static com.google.inject.name.Names.named; import com.google.inject.util.Providers; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * @author jessewilson@google.com (Jesse Wilson) */ public class BinderTestSuite { public static Test suite() { TestSuite suite = new TestSuite(); new Builder() .name("bind A") .module(new AbstractModule() { protected void configure() { bind(A.class); } }) .creationException("No implementation for %s was bound", A.class.getName()) .addToSuite(suite); new Builder() .name("bind PlainA named apple") .module(new AbstractModule() { protected void configure() { bind(PlainA.class).annotatedWith(named("apple")); } }) .creationException("No implementation for %s annotated with %s was bound", PlainA.class.getName(), named("apple")) .addToSuite(suite); new Builder() .name("bind A to new PlainA(1)") .module(new AbstractModule() { protected void configure() { bind(A.class).toInstance(new PlainA(1)); } }) .creationTime(CreationTime.NONE) .expectedValues(new PlainA(1), new PlainA(1), new PlainA(1)) .addToSuite(suite); new Builder() .name("no binding, AWithProvidedBy") .key(Key.get(AWithProvidedBy.class), InjectsAWithProvidedBy.class) .addToSuite(suite); new Builder() .name("no binding, AWithImplementedBy") .key(Key.get(AWithImplementedBy.class), InjectsAWithImplementedBy.class) .addToSuite(suite); new Builder() .name("no binding, ScopedA") .key(Key.get(ScopedA.class), InjectsScopedA.class) .expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202)) .addToSuite(suite); new Builder() .name("no binding, AWithProvidedBy named apple") .key(Key.get(AWithProvidedBy.class, named("apple")), InjectsAWithProvidedByNamedApple.class) .configurationException("No implementation for %s annotated with %s was bound", AWithProvidedBy.class.getName(), named("apple")) .addToSuite(suite); new Builder() .name("no binding, AWithImplementedBy named apple") .key(Key.get(AWithImplementedBy.class, named("apple")), InjectsAWithImplementedByNamedApple.class) .configurationException("No implementation for %s annotated with %s was bound", AWithImplementedBy.class.getName(), named("apple")) .addToSuite(suite); new Builder() .name("no binding, ScopedA named apple") .key(Key.get(ScopedA.class, named("apple")), InjectsScopedANamedApple.class) .configurationException("No implementation for %s annotated with %s was bound", ScopedA.class.getName(), named("apple")) .addToSuite(suite); for (final Scoper scoper : Scoper.values()) { new Builder() .name("bind PlainA") .key(Key.get(PlainA.class), InjectsPlainA.class) .module(new AbstractModule() { protected void configure() { AnnotatedBindingBuilder abb = bind(PlainA.class); scoper.configure(abb); } }) .scoper(scoper) .addToSuite(suite); new Builder() .name("bind A to PlainA") .module(new AbstractModule() { protected void configure() { ScopedBindingBuilder sbb = bind(A.class).to(PlainA.class); scoper.configure(sbb); } }) .scoper(scoper) .addToSuite(suite); new Builder() .name("bind A to PlainAProvider.class") .module(new AbstractModule() { protected void configure() { ScopedBindingBuilder sbb = bind(A.class).toProvider(PlainAProvider.class); scoper.configure(sbb); } }) .scoper(scoper) .addToSuite(suite); new Builder() .name("bind A to new PlainAProvider()") .module(new AbstractModule() { protected void configure() { ScopedBindingBuilder sbb = bind(A.class).toProvider(new PlainAProvider()); scoper.configure(sbb); } }) .scoper(scoper) .addToSuite(suite); new Builder() .name("bind AWithProvidedBy") .key(Key.get(AWithProvidedBy.class), InjectsAWithProvidedBy.class) .module(new AbstractModule() { protected void configure() { ScopedBindingBuilder sbb = bind(AWithProvidedBy.class); scoper.configure(sbb); } }) .scoper(scoper) .addToSuite(suite); new Builder() .name("bind AWithImplementedBy") .key(Key.get(AWithImplementedBy.class), InjectsAWithImplementedBy.class) .module(new AbstractModule() { protected void configure() { ScopedBindingBuilder sbb = bind(AWithImplementedBy.class); scoper.configure(sbb); } }) .scoper(scoper) .addToSuite(suite); new Builder() .name("bind ScopedA") .key(Key.get(ScopedA.class), InjectsScopedA.class) .module(new AbstractModule() { protected void configure() { ScopedBindingBuilder sbb = bind(ScopedA.class); scoper.configure(sbb); } }) .expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202)) .scoper(scoper) .addToSuite(suite); new Builder() .name("bind AWithProvidedBy named apple") .module(new AbstractModule() { protected void configure() { scoper.configure(bind(AWithProvidedBy.class).annotatedWith(named("apple"))); } }) .creationException("No implementation for %s annotated with %s was bound", AWithProvidedBy.class.getName(), named("apple")) .addToSuite(suite); new Builder() .name("bind AWithImplementedBy named apple") .module(new AbstractModule() { protected void configure() { scoper.configure(bind(AWithImplementedBy.class).annotatedWith(named("apple"))); } }) .creationException("No implementation for %s annotated with %s was bound", AWithImplementedBy.class.getName(), named("apple")) .addToSuite(suite); new Builder() .name("bind ScopedA named apple") .module(new AbstractModule() { protected void configure() { scoper.configure(bind(ScopedA.class).annotatedWith(named("apple"))); } }) .creationException("No implementation for %s annotated with %s was bound", ScopedA.class.getName(), named("apple")) .addToSuite(suite); } return suite; } enum Scoper { UNSCOPED { void configure(ScopedBindingBuilder sbb) {} void apply(Builder builder) {} }, EAGER_SINGLETON { void configure(ScopedBindingBuilder sbb) { sbb.asEagerSingleton(); } void apply(Builder builder) { builder.expectedValues(new PlainA(101), new PlainA(101), new PlainA(101)); builder.creationTime(CreationTime.EAGER); } }, SCOPES_SINGLETON { void configure(ScopedBindingBuilder sbb) { sbb.in(Scopes.SINGLETON); } void apply(Builder builder) { builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(201)); } }, SINGLETON_DOT_CLASS { void configure(ScopedBindingBuilder sbb) { sbb.in(Singleton.class); } void apply(Builder builder) { builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(201)); } }, TWO_AT_A_TIME_SCOPED_DOT_CLASS { void configure(ScopedBindingBuilder sbb) { sbb.in(TwoAtATimeScoped.class); } void apply(Builder builder) { builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202)); } }, TWO_AT_A_TIME_SCOPE { void configure(ScopedBindingBuilder sbb) { sbb.in(new TwoAtATimeScope()); } void apply(Builder builder) { builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202)); } }; abstract void configure(ScopedBindingBuilder sbb); abstract void apply(Builder builder); } /** When Guice creates a value, directly or via a provider */ enum CreationTime { NONE, EAGER, LAZY } public static class Builder { private String name = "test"; private Key key = Key.get(A.class); private Class injectsKey = InjectsA.class; private List modules = Lists.newArrayList(new AbstractModule() { protected void configure() { bindScope(TwoAtATimeScoped.class, new TwoAtATimeScope()); } }); private List expectedValues = Lists.newArrayList( new PlainA(201), new PlainA(202), new PlainA(203)); private CreationTime creationTime = CreationTime.LAZY; private String creationException; private String configurationException; public Builder module(Module module) { this.modules.add(module); return this; } public Builder creationTime(CreationTime creationTime) { this.creationTime = creationTime; return this; } public Builder name(String name) { this.name = name; return this; } public Builder key(Key key, Class injectsKey) { this.key = key; this.injectsKey = injectsKey; return this; } private Builder creationException(String message, Object... args) { this.creationException = String.format(message, args); return this; } private Builder configurationException(String message, Object... args) { configurationException = String.format(message, args); return this; } private Builder scoper(Scoper scoper) { name(name + " in " + scoper.toString()); scoper.apply(this); return this; } private Builder expectedValues(T... values) { this.expectedValues.clear(); this.expectedValues.addAll(Arrays.asList(values)); return this; } public void addToSuite(TestSuite suite) { if (creationException != null) { suite.addTest(new CreationExceptionTest(this)); } else if (configurationException != null) { suite.addTest(new ConfigurationExceptionTest(this)); } else { suite.addTest(new SuccessTest(this)); if (creationTime != CreationTime.NONE) { suite.addTest(new UserExceptionsTest(this)); } } } } public static class SuccessTest extends TestCase { final String name; final Key key; final Class injectsKey; final ImmutableList modules; final ImmutableList expectedValues; public SuccessTest(Builder builder) { super("test"); name = builder.name; key = builder.key; injectsKey = builder.injectsKey; modules = ImmutableList.copyOf(builder.modules); expectedValues = ImmutableList.copyOf(builder.expectedValues); } public String getName() { return name; } Injector newInjector() { nextId.set(101); return Guice.createInjector(modules); } public void test() throws IllegalAccessException, InstantiationException { Injector injector = newInjector(); nextId.set(201); for (Object value : expectedValues) { assertEquals(value, injector.getInstance(key)); } Provider provider = newInjector().getProvider(key); nextId.set(201); for (Object value : expectedValues) { assertEquals(value, provider.get()); } Provider bindingProvider = newInjector().getBinding(key).getProvider(); nextId.set(201); for (Object value : expectedValues) { assertEquals(value, bindingProvider.get()); } injector = newInjector(); nextId.set(201); for (Object value : expectedValues) { Injectable instance = injector.getInstance(injectsKey); assertEquals(value, instance.value); } injector = newInjector(); nextId.set(201); for (Object value : expectedValues) { Injectable injectable = injectsKey.newInstance(); injector.injectMembers(injectable); assertEquals(value, injectable.value); } Injector injector1 = newInjector(); nextId.set(201); Injectable hasProvider = injector1.getInstance(injectsKey); hasProvider.provider.get(); nextId.set(201); for (Object value : expectedValues) { assertEquals(value, hasProvider.provider.get()); } } } public static class CreationExceptionTest extends TestCase { final String name; final Key key; final ImmutableList modules; final String creationException; public CreationExceptionTest(Builder builder) { super("test"); name = builder.name; key = builder.key; modules = ImmutableList.copyOf(builder.modules); creationException = builder.creationException; } public String getName() { return "creation errors:" + name; } public void test() { try { Guice.createInjector(modules); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), creationException); } } } public static class ConfigurationExceptionTest extends TestCase { final String name; final Key key; final Class injectsKey; final ImmutableList modules; final String configurationException; public ConfigurationExceptionTest(Builder builder) { super("test"); name = builder.name; key = builder.key; injectsKey = builder.injectsKey; modules = ImmutableList.copyOf(builder.modules); configurationException = builder.configurationException; } public String getName() { return "provision errors:" + name; } Injector newInjector() { return Guice.createInjector(modules); } public void test() throws IllegalAccessException, InstantiationException { try { newInjector().getProvider(key); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), configurationException); } try { newInjector().getBinding(key).getProvider(); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), configurationException); } try { newInjector().getInstance(key); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), configurationException); } try { newInjector().getInstance(injectsKey); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), configurationException, injectsKey.getName() + ".inject", configurationException, injectsKey.getName() + ".inject", "2 errors"); } try { Injectable injectable = injectsKey.newInstance(); newInjector().injectMembers(injectable); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), configurationException, injectsKey.getName() + ".inject", configurationException, injectsKey.getName() + ".inject", "2 errors"); } } } public static class UserExceptionsTest extends TestCase { final String name; final Key key; final Class injectsKey; final ImmutableList modules; final ImmutableList expectedValues; final CreationTime creationTime; public UserExceptionsTest(Builder builder) { super("test"); name = builder.name; key = builder.key; injectsKey = builder.injectsKey; modules = ImmutableList.copyOf(builder.modules); expectedValues = ImmutableList.copyOf(builder.expectedValues); creationTime = builder.creationTime; } public String getName() { return "provision errors:" + name; } Injector newInjector() { return Guice.createInjector(modules); } public void test() throws IllegalAccessException, InstantiationException { nextId.set(-1); try { newInjector(); assertEquals(CreationTime.LAZY, creationTime); } catch (CreationException expected) { assertEquals(CreationTime.EAGER, creationTime); assertContains(expected.getMessage(), "Illegal value: -1"); return; } Provider provider = newInjector().getProvider(key); Provider bindingProvider = newInjector().getBinding(key).getProvider(); nextId.set(-1); try { newInjector().getInstance(key); fail(); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "Illegal value: -1"); } nextId.set(-1); try { provider.get(); fail(); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "Illegal value: -1"); } nextId.set(-1); try { bindingProvider.get(); fail(); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "Illegal value: -1"); } try { nextId.set(-1); newInjector().getInstance(injectsKey); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "Illegal value: -1", "for parameter 0 at " + injectsKey.getName() + ".inject"); } nextId.set(201); Injectable injectable = injectsKey.newInstance(); try { nextId.set(-1); newInjector().injectMembers(injectable); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "Illegal value: -1", "for parameter 0 at " + injectsKey.getName() + ".inject"); } nextId.set(201); Injectable hasProvider = newInjector().getInstance(injectsKey); hasProvider.provider.get(); try { nextId.set(-1); hasProvider.provider.get(); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "Illegal value: -1"); } } } /** negative to throw, 101... for eager singletons, 201... for everything else */ static final AtomicInteger nextId = new AtomicInteger(); @ProvidedBy(PlainAProvider.class) interface AWithProvidedBy {} static class InjectsAWithProvidedBy extends Injectable { @Inject public void inject(AWithProvidedBy aWithProvidedBy, Provider aWithProvidedByProvider) { this.value = aWithProvidedBy; this.provider = aWithProvidedByProvider; } } static class InjectsAWithProvidedByNamedApple extends Injectable { @Inject public void inject(@Named("apple") AWithProvidedBy aWithProvidedBy, @Named("apple") Provider aWithProvidedByProvider) { this.value = aWithProvidedBy; this.provider = aWithProvidedByProvider; } } @ImplementedBy(PlainA.class) interface AWithImplementedBy {} static class InjectsAWithImplementedBy extends Injectable { @Inject public void inject(AWithImplementedBy aWithImplementedBy, Provider aWithImplementedByProvider) { this.value = aWithImplementedBy; this.provider = aWithImplementedByProvider; } } static class InjectsAWithImplementedByNamedApple extends Injectable { @Inject public void inject(@Named("apple") AWithImplementedBy aWithImplementedBy, @Named("apple") Provider aWithImplementedByProvider) { this.value = aWithImplementedBy; this.provider = aWithImplementedByProvider; } } interface A extends AWithProvidedBy, AWithImplementedBy {} static class InjectsA extends Injectable { @Inject public void inject(A a, Provider aProvider) { this.value = a; this.provider = aProvider; } } static class PlainA implements A { final int value; PlainA() { value = nextId.getAndIncrement(); if (value < 0) { throw new RuntimeException("Illegal value: " + value); } } PlainA(int value) { this.value = value; } public boolean equals(Object obj) { return obj instanceof PlainA && value == ((PlainA) obj).value; } public int hashCode() { return value; } public String toString() { return "PlainA#" + value; } } static class PlainAProvider implements Provider { public A get() { return new PlainA(); } } static class InjectsPlainA extends Injectable { @Inject public void inject(PlainA plainA, Provider plainAProvider) { this.value = plainA; this.provider = plainAProvider; } } /** This scope hands out each value exactly twice */ static class TwoAtATimeScope implements Scope { public Provider scope(Key key, final Provider unscoped) { return new Provider() { T instance; public T get() { if (instance == null) { instance = unscoped.get(); return instance; } else { T result = instance; instance = null; return result; } } }; } } @Target({ TYPE, METHOD }) @Retention(RUNTIME) @ScopeAnnotation public @interface TwoAtATimeScoped {} @TwoAtATimeScoped static class ScopedA extends PlainA {} static class InjectsScopedA extends Injectable { @Inject public void inject(ScopedA scopedA, Provider scopedAProvider) { this.value = scopedA; this.provider = scopedAProvider; } } static class InjectsScopedANamedApple extends Injectable { @Inject public void inject(@Named("apple") ScopedA scopedA, @Named("apple") Provider scopedAProvider) { this.value = scopedA; this.provider = scopedAProvider; } } static class Injectable { Object value = new Object(); Provider provider = Providers.of(new Object()); } } guice-3.0/core/test/com/google/inject/InjectorTest.java0000644000175000017500000002366511460132772023060 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import static com.google.inject.Asserts.assertNotSerializable; import java.io.IOException; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicReference; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class InjectorTest extends TestCase { @Retention(RUNTIME) @BindingAnnotation @interface Other {} @Retention(RUNTIME) @BindingAnnotation @interface S {} @Retention(RUNTIME) @BindingAnnotation @interface I {} public void testToStringDoesNotInfinitelyRecurse() { Injector injector = Guice.createInjector(Stage.TOOL); injector.toString(); injector.getBinding(Injector.class).toString(); } public void testProviderMethods() throws CreationException { final SampleSingleton singleton = new SampleSingleton(); final SampleSingleton other = new SampleSingleton(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(SampleSingleton.class).toInstance(singleton); bind(SampleSingleton.class) .annotatedWith(Other.class) .toInstance(other); } }); assertSame(singleton, injector.getInstance(Key.get(SampleSingleton.class))); assertSame(singleton, injector.getInstance(SampleSingleton.class)); assertSame(other, injector.getInstance(Key.get(SampleSingleton.class, Other.class))); } static class SampleSingleton {} public void testInjection() throws CreationException { Injector injector = createFooInjector(); Foo foo = injector.getInstance(Foo.class); assertEquals("test", foo.s); assertEquals("test", foo.bar.getTee().getS()); assertSame(foo.bar, foo.copy); assertEquals(5, foo.i); assertEquals(5, foo.bar.getI()); // Test circular dependency. assertSame(foo.bar, foo.bar.getTee().getBar()); } private Injector createFooInjector() throws CreationException { return Guice.createInjector(new AbstractModule() { protected void configure() { bind(Bar.class).to(BarImpl.class); bind(Tee.class).to(TeeImpl.class); bindConstant().annotatedWith(S.class).to("test"); bindConstant().annotatedWith(I.class).to(5); } }); } public void testGetInstance() throws CreationException { Injector injector = createFooInjector(); Bar bar = injector.getInstance(Key.get(Bar.class)); assertEquals("test", bar.getTee().getS()); assertEquals(5, bar.getI()); } public void testIntAndIntegerAreInterchangeable() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(I.class).to(5); } }); IntegerWrapper iw = injector.getInstance(IntegerWrapper.class); assertEquals(5, (int) iw.i); } public void testInjectorApiIsNotSerializable() throws IOException { Injector injector = Guice.createInjector(); assertNotSerializable(injector); assertNotSerializable(injector.getProvider(String.class)); assertNotSerializable(injector.getBinding(String.class)); for (Binding binding : injector.getBindings().values()) { assertNotSerializable(binding); } } static class IntegerWrapper { @Inject @I Integer i; } static class Foo { @Inject Bar bar; @Inject Bar copy; @Inject @S String s; int i; @Inject void setI(@I int i) { this.i = i; } } interface Bar { Tee getTee(); int getI(); } @Singleton static class BarImpl implements Bar { @Inject @I int i; Tee tee; @Inject void initialize(Tee tee) { this.tee = tee; } public Tee getTee() { return tee; } public int getI() { return i; } } interface Tee { String getS(); Bar getBar(); } static class TeeImpl implements Tee { final String s; @Inject Bar bar; @Inject TeeImpl(@S String s) { this.s = s; } public String getS() { return s; } public Bar getBar() { return bar; } } public void testInjectStatics() throws CreationException { Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(S.class).to("test"); bindConstant().annotatedWith(I.class).to(5); requestStaticInjection(Static.class); } }); assertEquals("test", Static.s); assertEquals(5, Static.i); } static class Static { @Inject @I static int i; static String s; @Inject static void setS(@S String s) { Static.s = s; } } public void testPrivateInjection() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toInstance("foo"); bind(int.class).toInstance(5); } }); Private p = injector.getInstance(Private.class); assertEquals("foo", p.fromConstructor); assertEquals(5, p.fromMethod); } static class Private { String fromConstructor; int fromMethod; @Inject private Private(String fromConstructor) { this.fromConstructor = fromConstructor; } @Inject private void setInt(int i) { this.fromMethod = i; } } public void testProtectedInjection() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toInstance("foo"); bind(int.class).toInstance(5); } }); Protected p = injector.getInstance(Protected.class); assertEquals("foo", p.fromConstructor); assertEquals(5, p.fromMethod); } static class Protected { String fromConstructor; int fromMethod; @Inject protected Protected(String fromConstructor) { this.fromConstructor = fromConstructor; } @Inject protected void setInt(int i) { this.fromMethod = i; } } public void testInstanceInjectionHappensAfterFactoriesAreSetUp() { Guice.createInjector(new AbstractModule() { protected void configure() { bind(Object.class).toInstance(new Object() { @Inject Runnable r; }); bind(Runnable.class).to(MyRunnable.class); } }); } public void testSubtypeNotProvided() { try { Guice.createInjector().getInstance(Money.class); fail(); } catch (ProvisionException expected) { assertContains(expected.getMessage(), Tree.class.getName() + " doesn't provide instances of " + Money.class.getName(), "while locating ", Tree.class.getName(), "while locating ", Money.class.getName()); } } public void testNotASubtype() { try { Guice.createInjector().getInstance(PineTree.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), Tree.class.getName() + " doesn't extend " + PineTree.class.getName(), "while locating ", PineTree.class.getName()); } } public void testRecursiveImplementationType() { try { Guice.createInjector().getInstance(SeaHorse.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "@ImplementedBy points to the same class it annotates.", "while locating ", SeaHorse.class.getName()); } } public void testRecursiveProviderType() { try { Guice.createInjector().getInstance(Chicken.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "@ProvidedBy points to the same class it annotates", "while locating ", Chicken.class.getName()); } } static class MyRunnable implements Runnable { public void run() {} } @ProvidedBy(Tree.class) static class Money {} static class Tree implements Provider { public Object get() { return "Money doesn't grow on trees"; } } @ImplementedBy(Tree.class) static class PineTree extends Tree {} @ImplementedBy(SeaHorse.class) static class SeaHorse {} @ProvidedBy(Chicken.class) static class Chicken implements Provider { public Chicken get() { return this; } } public void testJitBindingFromAnotherThreadDuringInjection() { final ExecutorService executorService = Executors.newSingleThreadExecutor(); final AtomicReference got = new AtomicReference(); Guice.createInjector(new AbstractModule() { protected void configure() { requestInjection(new Object() { @Inject void initialize(final Injector injector) throws ExecutionException, InterruptedException { Future future = executorService.submit(new Callable() { public JustInTime call() throws Exception { return injector.getInstance(JustInTime.class); } }); got.set(future.get()); } }); } }); assertNotNull(got.get()); } static class JustInTime {} } guice-3.0/core/test/com/google/inject/BoundInstanceInjectionTest.java0000644000175000017500000000675311460132772025701 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.name.Named; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class BoundInstanceInjectionTest extends TestCase { public void testInstancesAreInjected() throws CreationException { final O o = new O(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(O.class).toInstance(o); bind(int.class).toInstance(5); } }); assertEquals(5, o.fromMethod); } static class O { int fromMethod; @Inject void setInt(int i) { this.fromMethod = i; } } public void testProvidersAreInjected() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(O.class).toProvider(new Provider() { @Inject int i; public O get() { O o = new O(); o.setInt(i); return o; } }); bind(int.class).toInstance(5); } }); assertEquals(5, injector.getInstance(O.class).fromMethod); } public void testMalformedInstance() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(Object.class).toInstance(new MalformedInjectable()); } }); fail(); } catch (CreationException expected) { Asserts.assertContains(expected.getMessage(), MalformedInjectable.class.getName(), ".doublyAnnotated() has more than one ", "annotation annotated with @BindingAnnotation: ", Named.class.getName() + " and " + Another.class.getName()); } } public void testMalformedProvider() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toProvider(new MalformedProvider()); } }); fail(); } catch (CreationException expected) { Asserts.assertContains(expected.getMessage(), MalformedProvider.class.getName(), ".doublyAnnotated() has more than one ", "annotation annotated with @BindingAnnotation: ", Named.class.getName() + " and " + Another.class.getName()); } } static class MalformedInjectable { @Inject void doublyAnnotated(@Named("a") @Another String unused) {} } static class MalformedProvider implements Provider { @Inject void doublyAnnotated(@Named("a") @Another String s) {} public String get() { return "a"; } } @BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME) public @interface Another {} } guice-3.0/core/test/com/google/inject/ErrorHandlingTest.java0000644000175000017500000000667111460132772024037 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.name.Named; import com.google.inject.name.Names; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import java.util.List; /** * @author crazybob@google.com (Bob Lee) */ public class ErrorHandlingTest { public static void main(String[] args) throws CreationException { try { Guice.createInjector(new MyModule()); } catch (CreationException e) { e.printStackTrace(); System.err.println("--"); } Injector bad = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toProvider(new Provider() { public String get() { return null; } }); } }); try { bad.getInstance(String.class); } catch (Exception e) { e.printStackTrace(); System.err.println("--"); } try { bad.getInstance(NeedsString.class); } catch (Exception e) { e.printStackTrace(); System.err.println("--"); } } static class NeedsString { @Inject String mofo; } @Inject @Named("missing") static List missing = null; static class Foo { @Inject public Foo(Runnable r) {} @Inject void setNames(List names) {} } static class Bar { // Invalid constructor. Bar(String s) {} @Inject void setNumbers(@Named("numbers") List numbers) {} @Inject void bar(@Named("foo") String s) {} } static class Tee { @Inject String s; @Inject void tee(String s, int i) {} @Inject Invalid invalid; } static class Invalid { Invalid(String s) {} } @Singleton @GoodScope static class TooManyScopes { } @Target(ElementType.TYPE) @Retention(RUNTIME) @ScopeAnnotation @interface GoodScope {} @interface BadScope {} @ImplementedBy(String.class) interface I {} static class MyModule extends AbstractModule { protected void configure() { bind(Runnable.class); bind(Foo.class); bind(Bar.class); bind(Tee.class); bind(new TypeLiteral>() {}); bind(String.class).annotatedWith(Names.named("foo")).in(Named.class); bind(Key.get(Runnable.class)).to(Key.get(Runnable.class)); bind(TooManyScopes.class); bindScope(BadScope.class, Scopes.SINGLETON); bind(Object.class).toInstance(new Object() { @Inject void foo() { throw new RuntimeException(); } }); requestStaticInjection(ErrorHandlingTest.class); addError("I don't like %s", "you"); Object o = "2"; try { Integer i = (Integer) o; } catch (Exception e) { addError(e); } bind(Module.class).toInstance(this); bind(I.class); } } } guice-3.0/core/test/com/google/inject/JitBindingsTest.java0000644000175000017500000005465411534737600023514 0ustar drazzibdrazzib/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import static com.google.inject.JitBindingsTest.GetBindingCheck.ALLOW_BINDING_PROVIDER; import static com.google.inject.JitBindingsTest.GetBindingCheck.FAIL_ALL; import static com.google.inject.JitBindingsTest.GetBindingCheck.ALLOW_BINDING; import static com.google.inject.internal.util.ImmutableSet.of; import junit.framework.TestCase; import java.util.Set; /** * Some tests for {@link Binder#requireExplicitBindings()} * * @author sberlin@gmail.com (Sam Berlin) */ public class JitBindingsTest extends TestCase { private String jitFailed(Class clazz) { return jitFailed(TypeLiteral.get(clazz)); } private String jitFailed(TypeLiteral clazz) { return "Explicit bindings are required and " + clazz + " is not explicitly bound."; } private String inChildMessage(Class clazz) { return "Unable to create binding for " + clazz.getName() + ". It was already configured on one or more child injectors or private modules"; } public void testLinkedBindingWorks() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).to(FooImpl.class); } }); // Foo was explicitly bound ensureWorks(injector, Foo.class); // FooImpl was implicitly bound, it is an error to call getInstance or getProvider, // It is OK to call getBinding for introspection, but an error to get the provider // of the binding ensureFails(injector, ALLOW_BINDING, FooImpl.class); } public void testMoreBasicsWork() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).to(FooImpl.class); bind(Bar.class); bind(FooBar.class); } }); // Foo, Bar & FooBar was explicitly bound ensureWorks(injector, FooBar.class, Bar.class, Foo.class); // FooImpl was implicitly bound, it is an error to call getInstance or getProvider, // It is OK to call getBinding for introspection, but an error to get the provider // of the binding ensureFails(injector, ALLOW_BINDING, FooImpl.class); } public void testLinkedEagerSingleton() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).to(FooImpl.class).asEagerSingleton(); } }); // Foo was explicitly bound ensureWorks(injector, Foo.class); // FooImpl was implicitly bound, it is an error to call getInstance or getProvider, // It is OK to call getBinding for introspection, but an error to get the provider // of the binding ensureFails(injector, ALLOW_BINDING, FooImpl.class); } public void testBasicsWithEagerSingleton() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).to(FooImpl.class).asEagerSingleton(); bind(Bar.class); bind(FooBar.class); } }); // Foo, Bar & FooBar was explicitly bound ensureWorks(injector, FooBar.class, Bar.class, Foo.class); // FooImpl was implicitly bound, it is an error to call getInstance or getProvider, // It is OK to call getBinding for introspection, but an error to get the provider // of the binding ensureFails(injector, ALLOW_BINDING, FooImpl.class); } public void testLinkedToScoped() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder.requireExplicitBindings(); bind(Foo.class).to(ScopedFooImpl.class); } }); // Foo was explicitly bound ensureWorks(injector, Foo.class); // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider, // It is OK to call getBinding for introspection, but an error to get the provider // of the binding ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class); } public void testBasicsWithScoped() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).to(ScopedFooImpl.class); bind(Bar.class); bind(FooBar.class); } }); // Foo, Bar & FooBar was explicitly bound ensureWorks(injector, FooBar.class, Bar.class, Foo.class); // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider, // It is OK to call getBinding for introspection, but an error to get the provider // of the binding ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class); } public void testFailsIfInjectingScopedDirectlyWhenItIsntBound() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).to(ScopedFooImpl.class); bind(WantsScopedFooImpl.class); } }); fail(); } catch(CreationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(ScopedFooImpl.class)); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } } public void testLinkedProviderBindingWorks() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).toProvider(FooProvider.class); } }); // Foo was explicitly bound ensureWorks(injector, Foo.class); // FooImpl was not bound at all (even implicitly), it is an error // to call getInstance, getProvider, or getBinding. ensureFails(injector, FAIL_ALL, FooImpl.class); } public void testJitGetFails() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); } }).getInstance(Bar.class); fail("should have failed"); } catch(ConfigurationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class)); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } } public void testJitInjectionFails() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).to(FooImpl.class); bind(FooBar.class); } }); fail("should have failed"); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class)); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } } public void testJitProviderGetFails() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); } }).getProvider(Bar.class); fail("should have failed"); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class)); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } } public void testJitProviderInjectionFails() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).to(FooImpl.class); bind(ProviderFooBar.class); } }); fail("should have failed"); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class)); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } } public void testImplementedBy() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(ImplBy.class); } }); ensureWorks(injector, ImplBy.class); ensureFails(injector, ALLOW_BINDING, ImplByImpl.class); } public void testImplementedBySomethingThatIsAnnotated() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(ImplByScoped.class); } }); ensureWorks(injector, ImplByScoped.class); ensureFails(injector, ALLOW_BINDING, ImplByScopedImpl.class); } public void testProvidedBy() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(ProvBy.class); } }); ensureWorks(injector, ProvBy.class); ensureFails(injector, ALLOW_BINDING, ProvByProvider.class); } public void testProviderMethods() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); } @SuppressWarnings("unused") @Provides Foo foo() { return new FooImpl(); } }); ensureWorks(injector, Foo.class); } public void testChildInjectorInheritsOption() { Injector parent = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Bar.class); } }); ensureWorks(parent, Bar.class); ensureFails(parent, FAIL_ALL, FooImpl.class, FooBar.class, Foo.class); try { parent.createChildInjector(new AbstractModule() { @Override protected void configure() { bind(FooBar.class); } }); fail("should have failed"); } catch(CreationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(Foo.class)); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } Injector child = parent.createChildInjector(new AbstractModule() { @Override protected void configure() { bind(Foo.class).to(FooImpl.class); } }); ensureWorks(child, Foo.class, Bar.class); ensureFails(child, ALLOW_BINDING, FooImpl.class); ensureInChild(parent, FooImpl.class, FooBar.class, Foo.class); Injector grandchild = child.createChildInjector(new AbstractModule() { @Override protected void configure() { bind(FooBar.class); } }); ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class); ensureFails(grandchild, ALLOW_BINDING, FooImpl.class); ensureFails(child, ALLOW_BINDING, FooImpl.class); ensureInChild(parent, FooImpl.class, FooBar.class, Foo.class); } public void testChildInjectorAddsOption() { Injector parent = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Bar.class); } }); int totalParentBindings = parent.getAllBindings().size(); try { parent.createChildInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(FooBar.class); } }); fail("should have failed"); } catch(CreationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(Foo.class)); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } assertEquals(totalParentBindings, parent.getAllBindings().size()); Injector child = parent.createChildInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).to(FooImpl.class); } }); totalParentBindings++; // creating this child added FooImpl to the parent. assertEquals(totalParentBindings, parent.getAllBindings().size()); ensureWorks(child, Foo.class, Bar.class); ensureFails(child, ALLOW_BINDING_PROVIDER, FooImpl.class); // Make extra certain that if something tries to inject a FooImpl from child // that it fails, even if calling getBinding().getProvider works.. because // the binding is built with the parent injector. try { child.injectMembers(new Object() { @SuppressWarnings("unused") @Inject void inject(FooImpl fooImpl) {} }); fail(); } catch(ConfigurationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(FooImpl.class)); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } Injector grandchild = child.createChildInjector(new AbstractModule() { @Override protected void configure() { bind(FooBar.class); } }); assertEquals(totalParentBindings, parent.getAllBindings().size()); ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class); ensureFails(grandchild, ALLOW_BINDING_PROVIDER, FooImpl.class); ensureFails(child, ALLOW_BINDING_PROVIDER, FooImpl.class); // Make sure siblings of children don't inherit each others settings... // a new child should be able to get FooImpl. child = parent.createChildInjector(); ensureWorks(child, FooImpl.class); } public void testPrivateModulesInheritOptions() { try { Guice.createInjector(new AbstractModule() { protected void configure() { binder().requireExplicitBindings(); bind(Foo.class).to(FooImpl.class); install(new PrivateModule() { public void configure() { bind(FooBar.class); expose(FooBar.class); } }); } }); fail("should have failed"); } catch(CreationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class)); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { binder().requireExplicitBindings(); install(new PrivateModule() { public void configure() { bind(Foo.class).to(FooImpl.class); expose(Foo.class); } }); } }); ensureInChild(injector, FooImpl.class); } public void testPrivateModuleAddsOption() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class).to(FooImpl.class); // Fails because FooBar is in the private module, // and it wants Bar, but Bar would be JIT. install(new PrivateModule() { public void configure() { binder().requireExplicitBindings(); bind(FooBar.class); expose(FooBar.class); } }); } }); fail("should have failed"); } catch(CreationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class)); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } } public void testPrivateModuleSiblingsDontShareOption() { Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class).to(FooImpl.class); install(new PrivateModule() { public void configure() { binder().requireExplicitBindings(); } }); // This works, even though Bar is JIT, // because the requireExplicitBindings isn't shared // between sibling private modules. install(new PrivateModule() { public void configure() { bind(FooBar.class); expose(FooBar.class); } }); } }); } public void testTypeLiteralsCanBeInjected() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); bind(new TypeLiteral>() {}); bind(new TypeLiteral>() {}).toInstance(of("bar")); } }); WantsTypeLiterals foo = injector.getInstance(new Key>() {}); assertEquals(foo.literal.getRawType(), String.class); assertEquals(of("bar"), foo.set); } public void testMembersInjectorsCanBeInjected() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); } @Provides String data(MembersInjector mi) { String data = "foo"; mi.injectMembers(data); return data; } }); String data = injector.getInstance(String.class); assertEquals("foo", data); } private void ensureWorks(Injector injector, Class... classes) { for(int i = 0; i < classes.length; i++) { injector.getInstance(classes[i]); injector.getProvider(classes[i]).get(); injector.getBinding(classes[i]).getProvider().get(); } } enum GetBindingCheck { FAIL_ALL, ALLOW_BINDING, ALLOW_BINDING_PROVIDER } private void ensureFails(Injector injector, GetBindingCheck getBinding, Class... classes) { for(int i = 0; i < classes.length; i++) { try { injector.getInstance(classes[i]); fail("should have failed tring to retrieve class: " + classes[i]); } catch(ConfigurationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(classes[i])); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } try { injector.getProvider(classes[i]); fail("should have failed tring to retrieve class: " + classes[i]); } catch(ConfigurationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(classes[i])); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } if (getBinding == GetBindingCheck.ALLOW_BINDING || getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) { Binding binding = injector.getBinding(classes[i]); try { binding.getProvider(); if (getBinding != GetBindingCheck.ALLOW_BINDING_PROVIDER) { fail("should have failed trying to retrieve class: " + classes[i]); } } catch(ConfigurationException expected) { if (getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) { throw expected; } assertContains(expected.getMessage(), "1) " + jitFailed(classes[i])); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } } else { try { injector.getBinding(classes[i]); fail("should have failed tring to retrieve class: " + classes[i]); } catch(ConfigurationException expected) { assertContains(expected.getMessage(), "1) " + jitFailed(classes[i])); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } } } } private void ensureInChild(Injector injector, Class... classes) { for(int i = 0; i < classes.length; i++) { try { injector.getInstance(classes[i]); fail("should have failed tring to retrieve class: " + classes[i]); } catch(ConfigurationException expected) { assertContains(expected.getMessage(), "1) " + inChildMessage(classes[i])); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } try { injector.getProvider(classes[i]); fail("should have failed tring to retrieve class: " + classes[i]); } catch(ConfigurationException expected) { assertContains(expected.getMessage(), "1) " + inChildMessage(classes[i])); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } try { injector.getBinding(classes[i]); fail("should have failed tring to retrieve class: " + classes[i]); } catch(ConfigurationException expected) { assertContains(expected.getMessage(), "1) " + inChildMessage(classes[i])); assertTrue(expected.getMessage(), !expected.getMessage().contains("2) ")); } } } private static interface Foo {} private static class FooImpl implements Foo {} @Singleton private static class ScopedFooImpl implements Foo {} private static class WantsScopedFooImpl { @SuppressWarnings("unused") @Inject ScopedFooImpl scopedFoo; } private static class Bar {} private static class FooBar { @SuppressWarnings("unused") @Inject Foo foo; @SuppressWarnings("unused") @Inject Bar bar; } private static class ProviderFooBar { @SuppressWarnings("unused") @Inject Provider foo; @SuppressWarnings("unused") @Inject Provider bar; } private static class FooProvider implements Provider { public Foo get() { return new FooImpl(); } } @ImplementedBy(ImplByImpl.class) private static interface ImplBy {} private static class ImplByImpl implements ImplBy {} @ImplementedBy(ImplByScopedImpl.class) private static interface ImplByScoped {} @Singleton private static class ImplByScopedImpl implements ImplByScoped {} @ProvidedBy(ProvByProvider.class) private static interface ProvBy {} private static class ProvByProvider implements Provider { public ProvBy get() { return new ProvBy() {}; } } private static class WantsTypeLiterals { TypeLiteral literal; Set set; @Inject WantsTypeLiterals(TypeLiteral literal, Set set) { this.literal = literal; this.set = set; } } } guice-3.0/core/test/com/google/inject/ProvisionExceptionsTest.java0000644000175000017500000001457411460132772025334 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import java.io.IOException; import junit.framework.TestCase; import com.google.inject.internal.Errors; import com.google.inject.name.Named; import com.google.inject.name.Names; /** * Tests that ProvisionExceptions are readable and clearly indicate to the user what went wrong with * their code. * * @author sameb@google.com (Sam Berlin) */ public class ProvisionExceptionsTest extends TestCase { public void testConstructorRuntimeException() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bindConstant().annotatedWith(Names.named("runtime")).to(true); bind(Exploder.class).to(Explosion.class); bind(Tracer.class).to(TracerImpl.class); } }); try { injector.getInstance(Tracer.class); fail(); } catch(ProvisionException pe) { // Make sure our initial error message gives the user exception. Asserts.assertContains(pe.getMessage(), "1) Error injecting constructor", "java.lang.IllegalStateException: boom!"); assertEquals(1, pe.getErrorMessages().size()); assertEquals(IllegalStateException.class, pe.getCause().getClass()); assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass()); } } public void testConstructorCheckedException() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bindConstant().annotatedWith(Names.named("runtime")).to(false); bind(Exploder.class).to(Explosion.class); bind(Tracer.class).to(TracerImpl.class); } }); try { injector.getInstance(Tracer.class); fail(); } catch(ProvisionException pe) { // Make sure our initial error message gives the user exception. Asserts.assertContains(pe.getMessage(), "1) Error injecting constructor", "java.io.IOException: boom!"); assertEquals(1, pe.getErrorMessages().size()); assertEquals(IOException.class, pe.getCause().getClass()); assertEquals(IOException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass()); } } public void testCustomProvidersRuntimeException() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Exploder.class).toProvider(new Provider() { public Exploder get() { return Explosion.createRuntime(); } }); bind(Tracer.class).to(TracerImpl.class); } }); try { injector.getInstance(Tracer.class); fail(); } catch(ProvisionException pe) { // Make sure our initial error message gives the user exception. Asserts.assertContains(pe.getMessage(), "1) Error in custom provider", "java.lang.IllegalStateException: boom!"); assertEquals(1, pe.getErrorMessages().size()); assertEquals(IllegalStateException.class, pe.getCause().getClass()); assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass()); } } public void testProviderMethodRuntimeException() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Tracer.class).to(TracerImpl.class); } @Provides Exploder exploder() { return Explosion.createRuntime(); } }); try { injector.getInstance(Tracer.class); fail(); } catch(ProvisionException pe) { // Make sure our initial error message gives the user exception. Asserts.assertContains(pe.getMessage(), "1) Error in custom provider", "java.lang.IllegalStateException: boom!"); assertEquals(1, pe.getErrorMessages().size()); assertEquals(IllegalStateException.class, pe.getCause().getClass()); assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass()); } } public void testProviderMethodCheckedException() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Tracer.class).to(TracerImpl.class); } @Provides Exploder exploder() throws IOException { return Explosion.createChecked(); } }); try { injector.getInstance(Tracer.class); fail(); } catch(ProvisionException pe) { pe.printStackTrace(); // Make sure our initial error message gives the user exception. Asserts.assertContains(pe.getMessage(), "1) Error in custom provider", "java.io.IOException: boom!"); assertEquals(1, pe.getErrorMessages().size()); assertEquals(IOException.class, pe.getCause().getClass()); assertEquals(IOException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass()); } } private static interface Exploder {} public static class Explosion implements Exploder { @Inject public Explosion(@Named("runtime") boolean runtime) throws IOException { if(runtime) { throw new IllegalStateException("boom!"); } else { throw new IOException("boom!"); } } public static Explosion createRuntime() { try { return new Explosion(true); } catch(IOException iox) { throw new RuntimeException(); } } public static Explosion createChecked() throws IOException { return new Explosion(false); } } private static interface Tracer {} private static class TracerImpl implements Tracer { @Inject TracerImpl(Exploder explosion) { } } } guice-3.0/core/test/com/google/inject/SerializationTest.java0000644000175000017500000000326211460132772024107 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertSimilarWhenReserialized; import java.io.IOException; import java.io.Serializable; import java.util.List; import junit.framework.AssertionFailedError; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class SerializationTest extends TestCase { public void testAbstractModuleIsSerializable() throws IOException { Asserts.reserialize(new MyAbstractModule()); } static class MyAbstractModule extends AbstractModule implements Serializable { protected void configure() {} } public void testCreationExceptionIsSerializable() throws IOException { assertSimilarWhenReserialized(createCreationException()); } private CreationException createCreationException() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(List.class); } }); throw new AssertionFailedError(); } catch (CreationException e) { return e; } } static class A { @Inject B b; } static class B {} } guice-3.0/core/test/com/google/inject/SuperclassTest.java0000644000175000017500000000263411460132772023420 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class SuperclassTest extends TestCase { public void testSuperclassInjection() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class); } }); Provider creator = injector.getProvider(Sub.class); Sub sub = creator.get(); sub = creator.get(); sub = creator.get(); sub = creator.get(); sub = creator.get(); assertNotNull(sub.field); assertNotNull(sub.fromMethod); } static abstract class Super { @Inject Foo field; Foo fromMethod; @Inject void setC(Foo foo) { fromMethod = foo; } } static class Sub extends Super { } static class Foo {} } guice-3.0/core/test/com/google/inject/PerformanceComparison.java0000644000175000017500000001720411460132772024727 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.text.DecimalFormat; import java.util.concurrent.Callable; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertSame; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; /** * A semi-useless microbenchmark. Spring and Guice constuct the same object * graph a bunch of times, and we see who can construct the most per second. * As of this writing Guice is more than 50X faster. Also useful for comparing * pure Java configuration options. * * @author crazybob@google.com (Bob Lee) */ public class PerformanceComparison { public static void main(String[] args) throws Exception { // Once warm up. Takes lazy loading out of the equation and ensures we // created the graphs properly. validate(springFactory); validate(juiceFactory); validate(byHandFactory); for (int i2 = 0; i2 < 10; i2++) { iterate(springFactory, "Spring: "); iterate(juiceFactory, "Guice: "); iterate(byHandFactory, "By Hand: "); System.err.println(); } System.err.println("Concurrent:"); for (int i2 = 0; i2 < 10; i2++) { concurrentlyIterate(springFactory, "Spring: "); concurrentlyIterate(juiceFactory, "Guice: "); concurrentlyIterate(byHandFactory, "By Hand: "); System.err.println(); } } static final Callable springFactory = new Callable() { final DefaultListableBeanFactory beanFactory; { beanFactory = new DefaultListableBeanFactory(); RootBeanDefinition tee = new RootBeanDefinition(TeeImpl.class, true); tee.setLazyInit(true); ConstructorArgumentValues teeValues = new ConstructorArgumentValues(); teeValues.addGenericArgumentValue("test"); tee.setConstructorArgumentValues(teeValues); RootBeanDefinition bar = new RootBeanDefinition(BarImpl.class, false); ConstructorArgumentValues barValues = new ConstructorArgumentValues(); barValues.addGenericArgumentValue(new RuntimeBeanReference("tee")); barValues.addGenericArgumentValue(5); bar.setConstructorArgumentValues(barValues); RootBeanDefinition foo = new RootBeanDefinition(Foo.class, false); MutablePropertyValues fooValues = new MutablePropertyValues(); fooValues.addPropertyValue("i", 5); fooValues.addPropertyValue("bar", new RuntimeBeanReference("bar")); fooValues.addPropertyValue("copy", new RuntimeBeanReference("bar")); fooValues.addPropertyValue("s", "test"); foo.setPropertyValues(fooValues); beanFactory.registerBeanDefinition("foo", foo); beanFactory.registerBeanDefinition("bar", bar); beanFactory.registerBeanDefinition("tee", tee); } public Foo call() throws Exception { return (Foo) beanFactory.getBean("foo"); } }; static final Callable juiceFactory = new Callable() { final Provider fooProvider; { Injector injector; try { injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Tee.class).to(TeeImpl.class); bind(Bar.class).to(BarImpl.class); bind(Foo.class); bindConstant().annotatedWith(I.class).to(5); bindConstant().annotatedWith(S.class).to("test"); } }); } catch (CreationException e) { throw new RuntimeException(e); } fooProvider = injector.getProvider(Foo.class); } public Foo call() throws Exception { return fooProvider.get(); } }; static final Callable byHandFactory = new Callable() { final Tee tee = new TeeImpl("test"); public Foo call() throws Exception { Foo foo = new Foo(); foo.setI(5); foo.setS("test"); Bar bar = new BarImpl(tee, 5); Bar copy = new BarImpl(tee, 5); foo.setBar(bar); foo.setCopy(copy); return foo; } }; static void validate(Callable t) throws Exception { Foo foo = t.call(); assertEquals(5, foo.i); assertEquals("test", foo.s); assertSame(foo.bar.getTee(), foo.copy.getTee()); assertEquals(5, foo.bar.getI()); assertEquals("test", foo.bar.getTee().getS()); } static final DecimalFormat format = new DecimalFormat(); static void iterate(Callable callable, String label) { int count = 100000; long time = System.currentTimeMillis(); for (int i = 0; i < count; i++) { try { callable.call(); } catch (Exception e) { throw new RuntimeException(e); } } time = System.currentTimeMillis() - time; System.err.println(label + format.format(count * 1000 / time) + " creations/s"); } static void concurrentlyIterate(final Callable callable, String label) { int threadCount = 10; final int count = 10000; Thread[] threads = new Thread[threadCount]; for (int i = 0; i < threadCount; i++) { threads[i] = new Thread() { public void run() { for (int i = 0; i < count; i++) { try { validate(callable); } catch (Exception e) { throw new RuntimeException(e); } } } }; } long time = System.currentTimeMillis(); for (int i = 0; i < threadCount; i++) { threads[i].start(); } for (int i = 0; i < threadCount; i++) { try { threads[i].join(); } catch (InterruptedException e) { throw new RuntimeException(e); } } time = System.currentTimeMillis() - time; System.err.println(label + format.format(count * 1000 / time) + " creations/s"); } public static class Foo { Bar bar; Bar copy; String s; int i; @Inject public void setI(@I int i) { this.i = i; } @Inject public void setBar(Bar bar) { this.bar = bar; } @Inject public void setCopy(Bar copy) { this.copy = copy; } @Inject public void setS(@S String s) { this.s = s; } } interface Bar { Tee getTee(); int getI(); } public static class BarImpl implements Bar { final int i; final Tee tee; @Inject public BarImpl(Tee tee, @I int i) { this.tee = tee; this.i = i; } public Tee getTee() { return tee; } public int getI() { return i; } } interface Tee { String getS(); } @Singleton public static class TeeImpl implements Tee { final String s; @Inject public TeeImpl(@S String s) { this.s = s; } public String getS() { return s; } } @Retention(RUNTIME) @BindingAnnotation @interface I {} @Retention(RUNTIME) @BindingAnnotation @interface S {} } guice-3.0/core/test/com/google/inject/TypeLiteralInjectionTest.java0000644000175000017500000000664411460132772025402 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.util.Types; import static com.google.inject.util.Types.listOf; import java.util.List; import junit.framework.TestCase; /** * Demonstrates type reification. * * @author jessewilson@google.com (Jesse Wilson) */ public class TypeLiteralInjectionTest extends TestCase { public void testBindingToRawTypeLiteralIsNotAllowed() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(TypeLiteral.class).toInstance(TypeLiteral.get(String.class)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "Binding to core guice framework type is not allowed: TypeLiteral"); } } public void testBindingToParameterizedTypeLiteralIsNotAllowed() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(new TypeLiteral>() {}) .toInstance(TypeLiteral.get(String.class)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "Binding to core guice framework type is not allowed: TypeLiteral"); } } public void testInjectTypeLiteralWithRawTypes() { C c = Guice.createInjector().getInstance(C.class); assertEquals(TypeLiteral.get(String.class), c.string); assertEquals(TypeLiteral.get(A.class), c.a); try { Guice.createInjector().getInstance(B.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), TypeLiteral.class.getName() + "> " + "cannot be used as a key; It is not fully specified."); } } public void testInjectTypeLiteralWithClassTypes() { B b = Guice.createInjector().getInstance(new Key>() {}); assertEquals(TypeLiteral.get(String.class), b.string); assertEquals(TypeLiteral.get(Integer.class), b.t); assertEquals(TypeLiteral.get(listOf(Integer.class)), b.listOfT); assertEquals(TypeLiteral.get(listOf(Types.subtypeOf(Integer.class))), b.listOfWildcardT); } public void testInjectRawTypeLiteral() { try { Guice.createInjector().getInstance(TypeLiteral.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "Cannot inject a TypeLiteral that has no type parameter"); } } static class A { @Inject TypeLiteral string; @Inject TypeLiteral> listOfT; @Inject TypeLiteral> listOfWildcardT; } static class B extends A { @Inject TypeLiteral t; } static class C { @Inject TypeLiteral string; @Inject TypeLiteral a; T t; } } guice-3.0/core/test/com/google/inject/OptionalBindingTest.java0000644000175000017500000002172311460132772024354 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.name.Named; import com.google.inject.name.Names; import junit.framework.TestCase; /** * This test verifies the ways things are injected (ie. getInstance(), * injectMembers(), bind to instance, and bind to provider instance) for all * states of optional bindings (fields, methods, multiple-argument methods, * provider fields, provider methods, constructors). * * @author jessewilson@google.com (Jesse Wilson) */ public class OptionalBindingTest extends TestCase { private static final A injectA = new A() {}; private static final B injectB = new B() {}; private static final C injectC = new C() {}; private static final D injectD = new D() {}; private static final E injectE = new E() {}; private static final F injectF = new F() {}; private static final G injectG = new G() {}; private Module everythingModule = new AbstractModule() { protected void configure() { bind(A.class).toInstance(injectA); bind(B.class).toInstance(injectB); bind(C.class).toInstance(injectC); bind(D.class).toInstance(injectD); bind(E.class).annotatedWith(Names.named("e")).toInstance(injectE); bind(F.class).toInstance(injectF); bind(G.class).toInstance(injectG); } }; private Module partialModule = new AbstractModule() { protected void configure() { bind(C.class).toInstance(new C() {}); } }; private Module toInstanceModule = new AbstractModule() { protected void configure() { bind(HasOptionalInjections.class) .toInstance(new HasOptionalInjections()); } }; private Module toProviderInstanceModule = new AbstractModule() { protected void configure() { bind(HasOptionalInjections.class) .toProvider(new HasOptionalInjectionsProvider()); } }; private Module toProviderModule = new AbstractModule() { protected void configure() { bind(HasOptionalInjections.class) .toProvider(HasOptionalInjectionsProvider.class); } }; public void testEverythingInjectorGetInstance() { Guice.createInjector(everythingModule) .getInstance(HasOptionalInjections.class) .assertEverythingInjected(); } public void testPartialInjectorGetInstance() { Guice.createInjector(partialModule) .getInstance(HasOptionalInjections.class) .assertNothingInjected(); } public void testNothingInjectorGetInstance() { Guice.createInjector() .getInstance(HasOptionalInjections.class) .assertNothingInjected(); } public void testEverythingInjectorInjectMembers() { HasOptionalInjections instance = new HasOptionalInjections(); Guice.createInjector(everythingModule).injectMembers(instance); instance.assertEverythingInjected(); } public void testPartialInjectorInjectMembers() { HasOptionalInjections instance = new HasOptionalInjections(); Guice.createInjector(partialModule).injectMembers(instance); instance.assertNothingInjected(); } public void testNothingInjectorInjectMembers() { HasOptionalInjections instance = new HasOptionalInjections(); Guice.createInjector().injectMembers(instance); instance.assertNothingInjected(); } public void testEverythingInjectorToInstance() { Guice.createInjector(everythingModule, toInstanceModule) .getInstance(HasOptionalInjections.class) .assertEverythingInjected(); } public void testPartialInjectorToInstance() { Guice.createInjector(partialModule, toInstanceModule) .getInstance(HasOptionalInjections.class) .assertNothingInjected(); } public void testNothingInjectorToInstance() { Guice.createInjector(toInstanceModule) .getInstance(HasOptionalInjections.class) .assertNothingInjected(); } public void testEverythingInjectorToProviderInstance() { Guice.createInjector(everythingModule, toProviderInstanceModule) .getInstance(HasOptionalInjections.class) .assertEverythingInjected(); } public void testPartialInjectorToProviderInstance() { Guice.createInjector(partialModule, toProviderInstanceModule) .getInstance(HasOptionalInjections.class) .assertNothingInjected(); } public void testNothingInjectorToProviderInstance() { Guice.createInjector(toProviderInstanceModule) .getInstance(HasOptionalInjections.class) .assertNothingInjected(); } public void testEverythingInjectorToProvider() { Guice.createInjector(everythingModule, toProviderModule) .getInstance(HasOptionalInjections.class) .assertEverythingInjected(); } public void testPartialInjectorToProvider() { Guice.createInjector(partialModule, toProviderModule) .getInstance(HasOptionalInjections.class) .assertNothingInjected(); } public void testNothingInjectorToProvider() { Guice.createInjector(toProviderModule) .getInstance(HasOptionalInjections.class) .assertNothingInjected(); } static class HasOptionalInjections { A originalA = new A() {}; @Inject(optional=true) A a = originalA; // field injection B b; // method injection with one argument C c; // method injection with two arguments D d; // method injection with two arguments E e; // annotated injection @Inject(optional=true) Provider fProvider; // provider Provider gProvider; // method injection of provider boolean invoked0, invoked1, invoked2, invokedAnnotated, invokeProvider; @Inject(optional=true) void methodInjectZeroArguments() { invoked0 = true; } @Inject(optional=true) void methodInjectOneArgument(B b) { this.b = b; invoked1 = true; } @Inject(optional=true) void methodInjectTwoArguments(C c, D d) { this.c = c; this.d = d; invoked2 = true; } @Inject(optional=true) void methodInjectAnnotated(@Named("e") E e) { this.e = e; invokedAnnotated = true; } @Inject(optional=true) void methodInjectProvider(Provider gProvider) { this.gProvider = gProvider; invokeProvider = true; } void assertNothingInjected() { assertSame(originalA, a); assertNull(b); assertNull(c); assertNull(d); assertNull(e); assertNull(fProvider); assertNull(gProvider); assertTrue(invoked0); assertFalse(invoked1); assertFalse(invoked2); assertFalse(invokedAnnotated); } public void assertEverythingInjected() { assertNotSame(injectA, originalA); assertSame(injectA, a); assertSame(injectB, b); assertSame(injectC, c); assertSame(injectD, d); assertSame(injectE, e); assertSame(injectF, fProvider.get()); assertSame(injectG, gProvider.get()); assertTrue(invoked0); assertTrue(invoked1); assertTrue(invoked2); assertTrue(invokedAnnotated); } } static class HasOptionalInjectionsProvider extends HasOptionalInjections implements Provider { public HasOptionalInjections get() { return this; } } public void testOptionalConstructorBlowsUp() { try { Guice.createInjector().getInstance(HasOptionalConstructor.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "OptionalBindingTest$HasOptionalConstructor.() " + "is annotated @Inject(optional=true), but constructors cannot be optional."); } } static class HasOptionalConstructor { @Inject(optional=true) HasOptionalConstructor() {} } @Inject(optional=true) static A staticInjectA; public void testStaticInjection() { staticInjectA = injectA; Guice.createInjector(new AbstractModule() { protected void configure() { requestStaticInjection(OptionalBindingTest.class); } }); assertSame(staticInjectA, injectA); } /** * Test for bug 107, where we weren't doing optional injection properly for * indirect injections. */ public void testIndirectOptionalInjection() { Indirect indirect = Guice.createInjector().getInstance(Indirect.class); assertNotNull(indirect.hasOptionalInjections); indirect.hasOptionalInjections.assertNothingInjected(); } static class Indirect { @Inject HasOptionalInjections hasOptionalInjections; } interface A {} interface B {} interface C {} interface D {} interface E {} interface F {} interface G {} } guice-3.0/core/test/com/google/inject/ReflectionTest.java0000644000175000017500000000462211460132772023365 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class ReflectionTest extends TestCase { @Retention(RUNTIME) @BindingAnnotation @interface I {} public void testNormalBinding() throws CreationException { final Foo foo = new Foo(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Foo.class).toInstance(foo); } }); Binding fooBinding = injector.getBinding(Key.get(Foo.class)); assertSame(foo, fooBinding.getProvider().get()); assertNotNull(fooBinding.getSource()); assertEquals(Key.get(Foo.class), fooBinding.getKey()); } public void testConstantBinding() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(I.class).to(5); } }); Binding i = injector.getBinding(Key.get(int.class, I.class)); assertEquals(5, i.getProvider().get()); assertNotNull(i.getSource()); assertEquals(Key.get(int.class, I.class), i.getKey()); } public void testLinkedBinding() throws CreationException { final Bar bar = new Bar(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Bar.class).toInstance(bar); bind(Key.get(Foo.class)).to(Key.get(Bar.class)); } }); Binding fooBinding = injector.getBinding(Key.get(Foo.class)); assertSame(bar, fooBinding.getProvider().get()); assertNotNull(fooBinding.getSource()); assertEquals(Key.get(Foo.class), fooBinding.getKey()); } static class Foo {} static class Bar extends Foo {} } guice-3.0/core/test/com/google/inject/example/0000755000175000017500000000000011460132764021220 5ustar drazzibdrazzibguice-3.0/core/test/com/google/inject/example/ClientServiceWithDependencyInjection.java0000644000175000017500000000370011460132764031320 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.example; import static junit.framework.Assert.assertTrue; /** * @author crazybob@google.com (Bob Lee) */ public class ClientServiceWithDependencyInjection { // 62 lines public interface Service { void go(); } public static class ServiceImpl implements ClientServiceWithDependencyInjection.Service { public void go() { // ... } } public static class ServiceFactory { private ServiceFactory() {} private static final Service service = new ServiceImpl(); public static Service getInstance() { return service; } } public static class Client { private final Service service; public Client(Service service) { this.service = service; } public void go() { service.go(); } } public static class ClientFactory { private ClientFactory() {} public static Client getInstance() { Service service = ServiceFactory.getInstance(); return new Client(service); } } public void testClient() { MockService mock = new MockService(); Client client = new Client(mock); client.go(); assertTrue(mock.isGone()); } public static class MockService implements Service { private boolean gone = false; public void go() { gone = true; } public boolean isGone() { return gone; } } public static void main(String[] args) { new ClientServiceWithDependencyInjection().testClient(); } } guice-3.0/core/test/com/google/inject/example/JndiProviderClient.java0000644000175000017500000000252611460132764025626 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.example; import com.google.inject.AbstractModule; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; import static com.google.inject.example.JndiProvider.fromJndi; import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; class JndiProviderClient { public static void main(String[] args) throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { // Bind Context to the default InitialContext. bind(Context.class).to(InitialContext.class); // Bind to DataSource from JNDI. bind(DataSource.class) .toProvider(fromJndi(DataSource.class, "...")); } }); } } guice-3.0/core/test/com/google/inject/example/ClientServiceWithFactories.java0000644000175000017500000000360611460132764027323 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.example; import static junit.framework.Assert.assertTrue; /** * @author crazybob@google.com (Bob Lee) */ public class ClientServiceWithFactories { // 58 lines public interface Service { void go(); } public static class ServiceImpl implements Service { public void go() { // ... } } public static class ServiceFactory { private ServiceFactory() {} private static Service instance = new ServiceImpl(); public static Service getInstance() { return instance; } public static void setInstance(Service service) { instance = service; } } public static class Client { public void go() { Service service = ServiceFactory.getInstance(); service.go(); } } public void testClient() { Service previous = ServiceFactory.getInstance(); try { final MockService mock = new MockService(); ServiceFactory.setInstance(mock); Client client = new Client(); client.go(); assertTrue(mock.isGone()); } finally { ServiceFactory.setInstance(previous); } } public static class MockService implements Service { private boolean gone = false; public void go() { gone = true; } public boolean isGone() { return gone; } } public static void main(String[] args) { new ClientServiceWithFactories().testClient(); } } guice-3.0/core/test/com/google/inject/example/JndiProvider.java0000644000175000017500000000247311460132764024470 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.example; import com.google.inject.Inject; import com.google.inject.Provider; import javax.naming.Context; import javax.naming.NamingException; class JndiProvider implements Provider { @Inject Context context; final String name; final Class type; JndiProvider(Class type, String name) { this.name = name; this.type = type; } public T get() { try { return type.cast(context.lookup(name)); } catch (NamingException e) { throw new RuntimeException(e); } } /** * Creates a JNDI provider for the given * type and name. */ static Provider fromJndi( Class type, String name) { return new JndiProvider(type, name); } } guice-3.0/core/test/com/google/inject/example/ClientServiceWithGuice.java0000644000175000017500000000377611460132764026450 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.example; import com.google.inject.AbstractModule; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Scopes; import static junit.framework.Assert.assertTrue; /** * @author crazybob@google.com (Bob Lee) */ public class ClientServiceWithGuice { // 48 lines public interface Service { void go(); } public static class ServiceImpl implements Service { public void go() { // ... } } public static class MyModule extends AbstractModule { protected void configure() { bind(Service.class).to(ServiceImpl.class).in(Scopes.SINGLETON); } } public static class Client { private final Service service; @Inject public Client(Service service) { this.service = service; } public void go() { service.go(); } } public void testClient() { MockService mock = new MockService(); Client client = new Client(mock); client.go(); assertTrue(mock.isGone()); } public static class MockService implements Service { private boolean gone = false; public void go() { gone = true; } public boolean isGone() { return gone; } } public static void main(String[] args) throws CreationException { new ClientServiceWithGuice().testClient(); Injector injector = Guice.createInjector(new MyModule()); Client client = injector.getInstance(Client.class); } } guice-3.0/core/test/com/google/inject/example/ClientServiceWithGuiceDefaults.java0000644000175000017500000000365111460132764030130 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.example; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.ImplementedBy; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Singleton; import junit.framework.Assert; /** * @author crazybob@google.com (Bob Lee) */ public class ClientServiceWithGuiceDefaults { // 44 lines @ImplementedBy(ServiceImpl.class) public interface Service { void go(); } @Singleton public static class ServiceImpl implements ClientServiceWithGuiceDefaults.Service { public void go() { // ... } } public static class Client { private final Service service; @Inject public Client(Service service) { this.service = service; } public void go() { service.go(); } } public void testClient() { MockService mock = new MockService(); Client client = new Client(mock); client.go(); Assert.assertTrue(mock.isGone()); } public static class MockService implements Service { private boolean gone = false; public void go() { gone = true; } public boolean isGone() { return gone; } } public static void main(String[] args) throws CreationException { new ClientServiceWithGuiceDefaults().testClient(); Injector injector = Guice.createInjector(); Client client = injector.getProvider(Client.class).get(); } } guice-3.0/core/test/com/google/inject/BinderTest.java0000644000175000017500000004612511536225574022511 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import static com.google.inject.Asserts.assertNotSerializable; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Iterables; import com.google.inject.internal.util.Lists; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.spi.Message; import com.google.inject.util.Providers; import java.io.IOException; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.concurrent.Callable; import java.util.logging.Handler; import java.util.logging.LogRecord; import java.util.logging.Logger; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class BinderTest extends TestCase { private final Logger loggerToWatch = Logger.getLogger(Guice.class.getName()); private final List logRecords = Lists.newArrayList(); private final Handler fakeHandler = new Handler() { public void publish(LogRecord logRecord) { logRecords.add(logRecord); } public void flush() {} public void close() throws SecurityException {} }; Provider fooProvider; @Override protected void setUp() throws Exception { super.setUp(); loggerToWatch.addHandler(fakeHandler); } @Override protected void tearDown() throws Exception { loggerToWatch.removeHandler(fakeHandler); super.tearDown(); } public void testProviderFromBinder() { Guice.createInjector(new Module() { public void configure(Binder binder) { fooProvider = binder.getProvider(Foo.class); try { fooProvider.get(); } catch (IllegalStateException e) { /* expected */ } } }); assertNotNull(fooProvider.get()); } static class Foo {} public void testMissingBindings() { try { Guice.createInjector(new AbstractModule() { public void configure() { getProvider(Runnable.class); bind(Comparator.class); requireBinding(Key.get(new TypeLiteral>() {})); bind(Date.class).annotatedWith(Names.named("date")); } }); } catch (CreationException e) { assertEquals(4, e.getErrorMessages().size()); assertContains(e.getMessage(), "1) No implementation for java.lang.Runnable was bound.", "at " + getClass().getName(), "2) No implementation for " + Comparator.class.getName() + " was bound.", "at " + getClass().getName(), "3) No implementation for java.util.concurrent.Callable was bound.", "at " + getClass().getName(), "4) No implementation for java.util.Date annotated with @" + Named.class.getName() + "(value=date) was bound.", "at " + getClass().getName()); } } public void testMissingDependency() { try { Guice.createInjector(new AbstractModule() { public void configure() { bind(NeedsRunnable.class); } }); } catch (CreationException e) { assertEquals(1, e.getErrorMessages().size()); assertContains(e.getMessage(), "No implementation for java.lang.Runnable was bound.", "for field at " + NeedsRunnable.class.getName(), ".runnable(BinderTest.java:", "at " + getClass().getName(), ".configure(BinderTest.java:"); } } static class NeedsRunnable { @Inject Runnable runnable; } public void testDanglingConstantBinding() { try { Guice.createInjector(new AbstractModule() { @Override public void configure() { bindConstant(); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Missing constant value. Please call to(...).", "at " + getClass().getName()); } } public void testRecursiveBinding() { try { Guice.createInjector(new AbstractModule() { @Override public void configure() { bind(Runnable.class).to(Runnable.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Binding points to itself.", "at " + getClass().getName(), ".configure(BinderTest.java:"); } } public void testBindingNullConstant() { try { Guice.createInjector(new AbstractModule() { @Override public void configure() { String none = null; bindConstant().annotatedWith(Names.named("nullOne")).to(none); bind(String.class).annotatedWith(Names.named("nullTwo")).toInstance(none); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Binding to null instances is not allowed. Use toProvider(Providers.of(null))", "2) Binding to null instances is not allowed. Use toProvider(Providers.of(null))"); } } public void testToStringOnBinderApi() { try { Guice.createInjector(new AbstractModule() { @Override public void configure() { assertEquals("Binder", binder().toString()); assertEquals("Provider", getProvider(Integer.class).toString()); assertEquals("Provider>", getProvider(Key.get(new TypeLiteral>() {})).toString()); assertEquals("BindingBuilder", bind(Integer.class).toString()); assertEquals("BindingBuilder", bind(Integer.class).annotatedWith(Names.named("a")).toString()); assertEquals("ConstantBindingBuilder", bindConstant().toString()); assertEquals("ConstantBindingBuilder", bindConstant().annotatedWith(Names.named("b")).toString()); assertEquals("AnnotatedElementBuilder", binder().newPrivateBinder().expose(Integer.class).toString()); } }); fail(); } catch (CreationException ignored) { } } public void testNothingIsSerializableInBinderApi() { try { Guice.createInjector(new AbstractModule() { @Override public void configure() { try { assertNotSerializable(binder()); assertNotSerializable(getProvider(Integer.class)); assertNotSerializable(getProvider(Key.get(new TypeLiteral>() {}))); assertNotSerializable(bind(Integer.class)); assertNotSerializable(bind(Integer.class).annotatedWith(Names.named("a"))); assertNotSerializable(bindConstant()); assertNotSerializable(bindConstant().annotatedWith(Names.named("b"))); } catch (IOException e) { fail(e.getMessage()); } } }); fail(); } catch (CreationException ignored) { } } /** * Although {@code String[].class} isn't equal to {@code new * GenericArrayTypeImpl(String.class)}, Guice should treat these two types * interchangeably. */ public void testArrayTypeCanonicalization() { final String[] strings = new String[] { "A" }; final Integer[] integers = new Integer[] { 1 }; Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String[].class).toInstance(strings); bind(new TypeLiteral() {}).toInstance(integers); } }); assertSame(integers, injector.getInstance(Key.get(new TypeLiteral() {}))); assertSame(integers, injector.getInstance(new Key() {})); assertSame(integers, injector.getInstance(Integer[].class)); assertSame(strings, injector.getInstance(Key.get(new TypeLiteral() {}))); assertSame(strings, injector.getInstance(new Key() {})); assertSame(strings, injector.getInstance(String[].class)); try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(String[].class).toInstance(new String[] { "A" }); bind(new TypeLiteral() {}).toInstance(new String[] { "B" }); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) A binding to java.lang.String[] was already configured at " + getClass().getName(), "at " + getClass().getName(), ".configure(BinderTest.java:"); assertContains(expected.getMessage(), "1 error"); } // passes because duplicates are ignored injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String[].class).toInstance(strings); bind(new TypeLiteral() {}).toInstance(strings); } }); assertSame(strings, injector.getInstance(Key.get(new TypeLiteral() {}))); assertSame(strings, injector.getInstance(new Key() {})); assertSame(strings, injector.getInstance(String[].class)); } /** * Binding something to two different things should give an error. */ public void testSettingBindingTwice() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).toInstance("foo"); bind(String.class).toInstance("bar"); } }); fail(); } catch(CreationException expected) { assertContains(expected.getMessage(), "1) A binding to java.lang.String was already configured at " + getClass().getName(), "at " + getClass().getName(), ".configure(BinderTest.java:"); assertContains(expected.getMessage(), "1 error"); } } /** * Binding an @ImplementedBy thing to something else should also fail. */ public void testSettingAtImplementedByTwice() { try { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(HasImplementedBy1.class); bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {}); } }); fail(); } catch(CreationException expected) { expected.printStackTrace(); assertContains(expected.getMessage(), "1) A binding to " + HasImplementedBy1.class.getName() + " was already configured at " + getClass().getName(), "at " + getClass().getName(), ".configure(BinderTest.java:"); assertContains(expected.getMessage(), "1 error"); } } /** * See issue 614, Problem One * http://code.google.com/p/google-guice/issues/detail?id=614 */ public void testJitDependencyDoesntBlockOtherExplicitBindings() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(HasImplementedByThatNeedsAnotherImplementedBy.class); bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {}); } }); injector.getAllBindings(); // just validate it doesn't throw. // Also validate that we're using the explicit (and not @ImplementedBy) implementation assertFalse(injector.getInstance(HasImplementedBy1.class) instanceof ImplementsHasImplementedBy1); } /** * See issue 614, Problem Two * http://code.google.com/p/google-guice/issues/detail?id=614 */ public void testJitDependencyCanUseExplicitDependencies() { Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(HasImplementedByThatWantsExplicit.class); bind(JustAnInterface.class).toInstance(new JustAnInterface() {}); } }); } /** * Untargetted bindings should follow @ImplementedBy and @ProvidedBy * annotations if they exist. Otherwise the class should be constructed * directly. */ public void testUntargettedBinding() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(HasProvidedBy1.class); bind(HasImplementedBy1.class); bind(HasProvidedBy2.class); bind(HasImplementedBy2.class); bind(JustAClass.class); } }); assertNotNull(injector.getInstance(HasProvidedBy1.class)); assertNotNull(injector.getInstance(HasImplementedBy1.class)); assertNotSame(HasProvidedBy2.class, injector.getInstance(HasProvidedBy2.class).getClass()); assertSame(ExtendsHasImplementedBy2.class, injector.getInstance(HasImplementedBy2.class).getClass()); assertSame(JustAClass.class, injector.getInstance(JustAClass.class).getClass()); } public void testPartialInjectorGetInstance() { Injector injector = Guice.createInjector(); try { injector.getInstance(MissingParameter.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "1) Could not find a suitable constructor in " + NoInjectConstructor.class.getName(), "at " + MissingParameter.class.getName() + ".(BinderTest.java:"); } } public void testUserReportedError() { final Message message = new Message(getClass(), "Whoops!"); try { Guice.createInjector(new AbstractModule() { protected void configure() { addError(message); } }); fail(); } catch (CreationException expected) { assertSame(message, Iterables.getOnlyElement(expected.getErrorMessages())); } } public void testUserReportedErrorsAreAlsoLogged() { try { Guice.createInjector(new AbstractModule() { protected void configure() { addError(new Message(ImmutableList.of(), "Whoops!", new IllegalArgumentException())); } }); fail(); } catch (CreationException expected) { } LogRecord logRecord = Iterables.getOnlyElement(this.logRecords); assertContains(logRecord.getMessage(), "An exception was caught and reported. Message: java.lang.IllegalArgumentException"); } public void testBindingToProvider() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(new TypeLiteral>() {}).toInstance(Providers.of("A")); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Binding to Provider is not allowed.", "at " + BinderTest.class.getName(), "configure(BinderTest.java:"); } } public void testCannotBindToGuiceTypes() { final Named red = Names.named("red"); try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(AbstractModule.class).annotatedWith(red) .toProvider(Providers.of(null)); bind(Binder.class).annotatedWith(red).toProvider(Providers.of(null)); bind(Binding.class).annotatedWith(red).toProvider(Providers.of(null)); bind(Injector.class).annotatedWith(red).toProvider(Providers.of(null)); bind(Key.class).annotatedWith(red).toProvider(Providers.of(null)); bind(Module.class).annotatedWith(red).toProvider(Providers.of(null)); bind(Provider.class).annotatedWith(red).toProvider(Providers.of(null)); bind(Scope.class).annotatedWith(red).toProvider(Providers.of(null)); bind(TypeLiteral.class).annotatedWith(red).toProvider(Providers.of(null)); bind(new TypeLiteral>() {}).toProvider(Providers.>of(null)); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "Binding to core guice framework type is not allowed: AbstractModule.", "Binding to core guice framework type is not allowed: Binder.", "Binding to core guice framework type is not allowed: Binding.", "Binding to core guice framework type is not allowed: Injector.", "Binding to core guice framework type is not allowed: Key.", "Binding to core guice framework type is not allowed: Module.", "Binding to Provider is not allowed.", "Binding to core guice framework type is not allowed: Scope.", "Binding to core guice framework type is not allowed: TypeLiteral.", "Binding to core guice framework type is not allowed: Key."); } } static class MissingParameter { @Inject MissingParameter(NoInjectConstructor noInjectConstructor) {} } static class NoInjectConstructor { private NoInjectConstructor() {} } @ProvidedBy(HasProvidedBy1Provider.class) interface HasProvidedBy1 {} static class HasProvidedBy1Provider implements Provider { public HasProvidedBy1 get() { return new HasProvidedBy1() {}; } } @ImplementedBy(ImplementsHasImplementedBy1.class) interface HasImplementedBy1 {} static class ImplementsHasImplementedBy1 implements HasImplementedBy1 {} @ProvidedBy(HasProvidedBy2Provider.class) static class HasProvidedBy2 {} static class HasProvidedBy2Provider implements Provider { public HasProvidedBy2 get() { return new HasProvidedBy2() {}; } } @ImplementedBy(ExtendsHasImplementedBy2.class) static class HasImplementedBy2 {} static class ExtendsHasImplementedBy2 extends HasImplementedBy2 {} static class JustAClass {} @ImplementedBy(ImplementsHasImplementedByThatNeedsAnotherImplementedBy.class) static interface HasImplementedByThatNeedsAnotherImplementedBy { } static class ImplementsHasImplementedByThatNeedsAnotherImplementedBy implements HasImplementedByThatNeedsAnotherImplementedBy { @Inject ImplementsHasImplementedByThatNeedsAnotherImplementedBy( HasImplementedBy1 h1n1) {} } @ImplementedBy(ImplementsHasImplementedByThatWantsExplicit.class) static interface HasImplementedByThatWantsExplicit { } static class ImplementsHasImplementedByThatWantsExplicit implements HasImplementedByThatWantsExplicit { @Inject ImplementsHasImplementedByThatWantsExplicit(JustAnInterface jai) {} } static interface JustAnInterface {} // public void testBindInterfaceWithoutImplementation() { // Guice.createInjector(new AbstractModule() { // protected void configure() { // bind(Runnable.class); // } // }).getInstance(Runnable.class); // } enum Roshambo { ROCK, SCISSORS, PAPER } public void testInjectRawProvider() { try { Guice.createInjector().getInstance(Provider.class); fail(); } catch (ConfigurationException expected) { Asserts.assertContains(expected.getMessage(), "1) Cannot inject a Provider that has no type parameter", "while locating " + Provider.class.getName()); } } } guice-3.0/core/test/com/google/inject/ModulesTest.java0000644000175000017500000000477011460132772022707 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.util.Modules; import java.util.Arrays; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class ModulesTest extends TestCase { public void testCombineVarargs() { Module combined = Modules.combine(newModule(1), newModule(2L), newModule((short) 3)); Injector injector = Guice.createInjector(combined); assertEquals(1, injector.getInstance(Integer.class).intValue()); assertEquals(2L, injector.getInstance(Long.class).longValue()); assertEquals(3, injector.getInstance(Short.class).shortValue()); } public void testCombineIterable() { Iterable modules = Arrays.asList(newModule(1), newModule(2L), newModule((short) 3)); Injector injector = Guice.createInjector(Modules.combine(modules)); assertEquals(1, injector.getInstance(Integer.class).intValue()); assertEquals(2, injector.getInstance(Long.class).longValue()); assertEquals(3, injector.getInstance(Short.class).shortValue()); } /** * The module returned by Modules.combine shouldn't show up in binder sources. */ public void testCombineSources() { Module skipSourcesModule = new AbstractModule() { @Override protected void configure() { install(Modules.combine(newModule(1), newModule(2L))); } }; Injector injector = Guice.createInjector(Modules.combine(skipSourcesModule)); StackTraceElement source = (StackTraceElement) injector.getBinding(Integer.class).getSource(); assertEquals(skipSourcesModule.getClass().getName(), source.getClassName()); } private Module newModule(final T toBind) { return new AbstractModule() { protected void configure() { @SuppressWarnings("unchecked") // getClass always needs a cast Class tClass = (Class) toBind.getClass(); binder().skipSources(getClass()).bind(tClass).toInstance(toBind); } }; } } guice-3.0/core/test/com/google/inject/ModuleTest.java0000644000175000017500000000234711460132772022522 0ustar drazzibdrazzib// Copyright 2007 Google Inc. All Rights Reserved. package com.google.inject; import junit.framework.TestCase; /** * Tests relating to modules. * * @author kevinb */ public class ModuleTest extends TestCase { static class A implements Module { public void configure(Binder binder) { binder.bind(X.class); binder.install(new B()); binder.install(new C()); } } static class B implements Module { public void configure(Binder binder) { binder.bind(Y.class); binder.install(new D()); } } static class C implements Module { public void configure(Binder binder) { binder.bind(Z.class); binder.install(new D()); } } static class D implements Module { public void configure(Binder binder) { binder.bind(W.class); } @Override public boolean equals(Object obj) { return obj.getClass() == D.class; // we're all equal in the eyes of guice } @Override public int hashCode() { return D.class.hashCode(); } } static class X {} static class Y {} static class Z {} static class W {} public void testDiamond() throws Exception { Guice.createInjector(new A()); } } guice-3.0/core/test/com/google/inject/matcher/0000755000175000017500000000000011460132764021210 5ustar drazzibdrazzibguice-3.0/core/test/com/google/inject/matcher/MatcherTest.java0000644000175000017500000001567411460132764024313 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.matcher; import static com.google.inject.Asserts.assertEqualWhenReserialized; import static com.google.inject.Asserts.assertEqualsBothWays; import static com.google.inject.matcher.Matchers.annotatedWith; import static com.google.inject.matcher.Matchers.any; import static com.google.inject.matcher.Matchers.identicalTo; import static com.google.inject.matcher.Matchers.inPackage; import static com.google.inject.matcher.Matchers.inSubpackage; import static com.google.inject.matcher.Matchers.not; import static com.google.inject.matcher.Matchers.only; import static com.google.inject.matcher.Matchers.returns; import static com.google.inject.matcher.Matchers.subclassesOf; import com.google.inject.name.Named; import com.google.inject.name.Names; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; import java.util.AbstractList; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class MatcherTest extends TestCase { public void testAny() { assertTrue(any().matches(null)); assertEquals("any()", any().toString()); assertEqualsBothWays(any(), any()); assertFalse(any().equals(not(any()))); } public void testNot() { assertFalse(not(any()).matches(null)); assertEquals("not(any())", not(any()).toString()); assertEqualsBothWays(not(any()), not(any())); assertFalse(not(any()).equals(any())); } public void testAnd() { assertTrue(any().and(any()).matches(null)); assertFalse(any().and(not(any())).matches(null)); assertEquals("and(any(), any())", any().and(any()).toString()); assertEqualsBothWays(any().and(any()), any().and(any())); assertFalse(any().and(any()).equals(not(any()))); } public void testOr() { assertTrue(any().or(not(any())).matches(null)); assertFalse(not(any()).or(not(any())).matches(null)); assertEquals("or(any(), any())", any().or(any()).toString()); assertEqualsBothWays(any().or(any()), any().or(any())); assertFalse(any().or(any()).equals(not(any()))); } public void testAnnotatedWith() { assertTrue(annotatedWith(Foo.class).matches(Bar.class)); assertFalse(annotatedWith(Foo.class).matches( MatcherTest.class.getMethods()[0])); assertEquals("annotatedWith(Foo.class)", annotatedWith(Foo.class).toString()); assertEqualsBothWays(annotatedWith(Foo.class), annotatedWith(Foo.class)); assertFalse(annotatedWith(Foo.class).equals(annotatedWith(Named.class))); try { annotatedWith(Baz.class); fail(); } catch (IllegalArgumentException expected) { } } public void testSubclassesOf() { assertTrue(subclassesOf(Runnable.class).matches(Runnable.class)); assertTrue(subclassesOf(Runnable.class).matches(MyRunnable.class)); assertFalse(subclassesOf(Runnable.class).matches(Object.class)); assertEquals("subclassesOf(Runnable.class)", subclassesOf(Runnable.class).toString()); assertEqualsBothWays(subclassesOf(Runnable.class), subclassesOf(Runnable.class)); assertFalse(subclassesOf(Runnable.class).equals(subclassesOf(Object.class))); } public void testOnly() { assertTrue(only(1000).matches(1000)); assertFalse(only(1).matches(1000)); assertEquals("only(1)", only(1).toString()); assertEqualsBothWays(only(1), only(1)); assertFalse(only(1).equals(only(2))); } @SuppressWarnings("UnnecessaryBoxing") public void testIdenticalTo() { Object o = new Object(); assertEquals("identicalTo(1)", identicalTo(1).toString()); assertTrue(identicalTo(o).matches(o)); assertFalse(identicalTo(o).matches(new Object())); assertEqualsBothWays(identicalTo(o), identicalTo(o)); assertFalse(identicalTo(1).equals(identicalTo(new Integer(1)))); } public void testInPackage() { Package matchersPackage = Matchers.class.getPackage(); assertEquals("inPackage(com.google.inject.matcher)", inPackage(matchersPackage).toString()); assertTrue(inPackage(matchersPackage).matches(MatcherTest.class)); assertFalse(inPackage(matchersPackage).matches(Object.class)); assertEqualsBothWays(inPackage(matchersPackage), inPackage(matchersPackage)); assertFalse(inPackage(matchersPackage).equals(inPackage(Object.class.getPackage()))); } public void testInSubpackage() { String stringPackageName = String.class.getPackage().getName(); assertEquals("inSubpackage(java.lang)", inSubpackage(stringPackageName).toString()); assertTrue(inSubpackage(stringPackageName).matches(Object.class)); assertTrue(inSubpackage(stringPackageName).matches(Method.class)); assertFalse(inSubpackage(stringPackageName).matches(Matchers.class)); assertFalse(inSubpackage("jav").matches(Object.class)); assertEqualsBothWays(inSubpackage(stringPackageName), inSubpackage(stringPackageName)); assertFalse(inSubpackage(stringPackageName).equals(inSubpackage(Matchers.class.getPackage().getName()))); } public void testReturns() throws NoSuchMethodException { Matcher predicate = returns(only(String.class)); assertTrue(predicate.matches( Object.class.getMethod("toString"))); assertFalse(predicate.matches( Object.class.getMethod("hashCode"))); assertEquals("returns(only(class java.lang.String))", returns(only(String.class)).toString()); assertEqualsBothWays(predicate, returns(only(String.class))); assertFalse(predicate.equals(returns(only(Integer.class)))); } public void testSerialization() throws IOException { assertEqualWhenReserialized(any()); assertEqualWhenReserialized(not(any())); assertEqualWhenReserialized(annotatedWith(Named.class)); assertEqualWhenReserialized(annotatedWith(Names.named("foo"))); assertEqualWhenReserialized(only("foo")); assertEqualWhenReserialized(identicalTo(Object.class)); assertEqualWhenReserialized(inPackage(String.class.getPackage())); assertEqualWhenReserialized(inSubpackage(String.class.getPackage().getName())); assertEqualWhenReserialized(returns(any())); assertEqualWhenReserialized(subclassesOf(AbstractList.class)); assertEqualWhenReserialized(only("a").or(only("b"))); assertEqualWhenReserialized(only("a").and(only("b"))); } static abstract class MyRunnable implements Runnable {} @Retention(RetentionPolicy.RUNTIME) @interface Foo {} @Foo static class Bar {} @interface Baz {} @Baz static class Car {} } guice-3.0/core/test/com/google/inject/util/0000755000175000017500000000000011460132770020537 5ustar drazzibdrazzibguice-3.0/core/test/com/google/inject/util/NoopOverrideTest.java0000644000175000017500000000205311460132770024655 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.util; import com.google.inject.Module; import com.google.inject.spi.ElementVisitor; import com.google.inject.spi.ElementsTest; /** * @author jessewilson@google.com (Jesse Wilson) */ public class NoopOverrideTest extends ElementsTest { protected void checkModule(Module module, ElementVisitor... visitors) { Module overridden = Modules.override(module).with(Modules.EMPTY_MODULE); super.checkModule(overridden, visitors); } }guice-3.0/core/test/com/google/inject/util/TypesTest.java0000644000175000017500000002027711460132770023356 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.util; import static com.google.inject.Asserts.assertContains; import static com.google.inject.Asserts.assertEqualWhenReserialized; import static com.google.inject.Asserts.assertEqualsBothWays; import com.google.inject.TypeLiteral; import com.google.inject.internal.MoreTypes; import static com.google.inject.util.Types.subtypeOf; import static com.google.inject.util.Types.supertypeOf; import java.io.IOException; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.Assert; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class TypesTest extends TestCase { // generic types for comparison Map a; Inner b; List c; List d; Set e; Outer.Inner f; private ParameterizedType mapStringInteger; private ParameterizedType innerFloatDouble; private ParameterizedType listStringArray; private ParameterizedType listString; private ParameterizedType setString; private GenericArrayType stringArray; private ParameterizedType outerInner; protected void setUp() throws Exception { super.setUp(); mapStringInteger = (ParameterizedType) getClass().getDeclaredField("a").getGenericType(); innerFloatDouble = (ParameterizedType) getClass().getDeclaredField("b").getGenericType(); listStringArray = (ParameterizedType) getClass().getDeclaredField("c").getGenericType(); listString = (ParameterizedType) getClass().getDeclaredField("d").getGenericType(); setString = (ParameterizedType) getClass().getDeclaredField("e").getGenericType(); stringArray = (GenericArrayType) listStringArray.getActualTypeArguments()[0]; outerInner = (ParameterizedType) getClass().getDeclaredField("f").getGenericType(); } public void testListSetMap() { assertEqualsBothWays(mapStringInteger, Types.mapOf(String.class, Integer.class)); assertEqualsBothWays(listString, Types.listOf(String.class)); assertEqualsBothWays(setString, Types.setOf(String.class)); } public void testDefensiveCopies() { Type[] arguments = new Type[] { String.class, Integer.class }; ParameterizedType parameterizedType = Types.newParameterizedType(Map.class, arguments); arguments[0] = null; assertEquals(String.class, parameterizedType.getActualTypeArguments()[0]); parameterizedType.getActualTypeArguments()[1] = null; assertEquals(Integer.class, parameterizedType.getActualTypeArguments()[1]); } public void testTypeWithOwnerType() { ParameterizedType actual = Types.newParameterizedTypeWithOwner( TypesTest.class, Inner.class, Float.class, Double.class); assertEquals(TypesTest.class, actual.getOwnerType()); assertEqualsBothWays(innerFloatDouble, actual); // The JDK prints this out as: // com.google.inject.util.TypesTest.com.google.inject.util.TypesTest$Inner // and we think that's wrong, so the assertEquals comparison is worthless. :-( // assertEquals(innerFloatDouble.toString(), actual.toString()); // We think the correct comparison is: assertEquals("com.google.inject.util.TypesTest$Inner", actual.toString()); } public void testTypeParametersMustNotBePrimitives() { try { Types.newParameterizedType(Map.class, String.class, int.class); fail(); } catch (IllegalArgumentException expected) { assertContains(expected.getMessage(), "Primitive types are not allowed in type parameters: int"); } } public List wildcardExtends; public List wildcardSuper; public List wildcardObject; public void testWildcardTypes() throws NoSuchFieldException, IOException { assertEqualsBothWays(getWildcard("wildcardSuper"), supertypeOf(CharSequence.class)); assertEqualsBothWays(getWildcard("wildcardExtends"), subtypeOf(CharSequence.class)); assertEqualsBothWays(getWildcard("wildcardObject"), subtypeOf(Object.class)); assertEquals("? super java.lang.CharSequence", supertypeOf(CharSequence.class).toString()); assertEquals("? extends java.lang.CharSequence", subtypeOf(CharSequence.class).toString()); assertEquals("?", subtypeOf(Object.class).toString()); assertEqualWhenReserialized(supertypeOf(CharSequence.class)); assertEqualWhenReserialized(subtypeOf(CharSequence.class)); } public void testWildcardBoundsMustNotBePrimitives() { try { supertypeOf(int.class); fail(); } catch (IllegalArgumentException expected) { assertContains(expected.getMessage(), "Primitive types are not allowed in wildcard bounds: int"); } try { subtypeOf(int.class); fail(); } catch (IllegalArgumentException expected) { assertContains(expected.getMessage(), "Primitive types are not allowed in wildcard bounds: int"); } } private WildcardType getWildcard(String fieldName) throws NoSuchFieldException { ParameterizedType type = (ParameterizedType) getClass().getField(fieldName).getGenericType(); return (WildcardType) type.getActualTypeArguments()[0]; } public void testEqualsAndHashcode() { ParameterizedType parameterizedType = Types.newParameterizedType(Map.class, String.class, Integer.class); assertEqualsBothWays(mapStringInteger, parameterizedType); assertEquals(mapStringInteger.toString(), parameterizedType.toString()); GenericArrayType genericArrayType = Types.arrayOf( Types.arrayOf(String.class)); assertEqualsBothWays(stringArray, genericArrayType); assertEquals(stringArray.toString(), genericArrayType.toString()); } public void testToString() { Assert.assertEquals("java.lang.String", MoreTypes.typeToString(String.class)); assertEquals("java.lang.String[][]", MoreTypes.typeToString(stringArray)); assertEquals("java.util.Map", MoreTypes.typeToString(mapStringInteger)); assertEquals("java.util.List", MoreTypes.typeToString(listStringArray)); assertEquals(innerFloatDouble.toString(), MoreTypes.typeToString(innerFloatDouble)); } static class Owning {} /** * Ensure that owning types are required when necessary, and forbidden * otherwise. */ public void testCanonicalizeRequiresOwnerTypes() throws NoSuchFieldException { try { Types.newParameterizedType(Owning.class, String.class); fail(); } catch (IllegalArgumentException expected) { assertContains(expected.getMessage(), "No owner type for enclosed " + Owning.class); } try { Types.newParameterizedTypeWithOwner(Object.class, Set.class, String.class); } catch (IllegalArgumentException expected) { assertContains(expected.getMessage(), "Owner type for unenclosed " + Set.class); } } @SuppressWarnings("UnusedDeclaration") class Inner {} public void testInnerParameterizedEvenWithZeroArgs() { TypeLiteral.Inner> type = new TypeLiteral.Inner>() {}; assertEqualsBothWays(outerInner, type.getType()); ParameterizedType parameterizedType = (ParameterizedType) type.getType(); assertEquals(0, parameterizedType.getActualTypeArguments().length); assertEquals(new TypeLiteral>() {}.getType(), parameterizedType.getOwnerType()); assertEquals(Outer.Inner.class, parameterizedType.getRawType()); } static class Outer { class Inner {} } } guice-3.0/core/test/com/google/inject/util/ProvidersTest.java0000644000175000017500000000220211460132770024213 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.util; import com.google.inject.Provider; import junit.framework.TestCase; /** * Unit tests for {@link Providers}. * * @author Kevin Bourrillion (kevinb9n@gmail.com) */ public class ProvidersTest extends TestCase { public void testOfInstance() { String foo = "foo"; Provider p = Providers.of(foo); assertSame(foo, p.get()); assertSame(foo, p.get()); } public void testOfNull() { Provider p = Providers.of(null); assertNull(p.get()); } } guice-3.0/core/test/com/google/inject/ParentInjectorTest.java0000644000175000017500000002452511532235610024221 0ustar drazzibdrazzib/* Copyright (C) 2007 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Iterables; import com.google.inject.matcher.Matchers; import com.google.inject.name.Names; import com.google.inject.spi.TypeConverter; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import java.util.List; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class ParentInjectorTest extends TestCase { public void testParentAndChildCannotShareExplicitBindings() { Injector parent = Guice.createInjector(bindsA); try { parent.createChildInjector(bindsA); fail("Created the same explicit binding on both parent and child"); } catch (CreationException e) { assertContains(e.getMessage(), "A binding to ", A.class.getName(), " was already configured", " at ", getClass().getName(), ".configure(ParentInjectorTest.java:", " at ", getClass().getName(), ".configure(ParentInjectorTest.java:"); } } public void testParentJitBindingWontClobberChildBinding() { Injector parent = Guice.createInjector(); parent.createChildInjector(bindsA); try { parent.getInstance(A.class); fail("Created a just-in-time binding on the parent that's the same as a child's binding"); } catch (ConfigurationException e) { assertContains(e.getMessage(), "Unable to create binding for " + A.class.getName(), "It was already configured on one or more child injectors or private modules", "bound at " + bindsA.getClass().getName() + ".configure(", "If it was in a PrivateModule, did you forget to expose the binding?", "while locating " + A.class.getName()); } } public void testChildCannotBindToAParentJitBinding() { Injector parent = Guice.createInjector(); parent.getInstance(A.class); try { parent.createChildInjector(bindsA); fail(); } catch(CreationException ce) { assertContains(Iterables.getOnlyElement(ce.getErrorMessages()).getMessage(), "A just-in-time binding to " + A.class.getName() + " was already configured on a parent injector."); } } public void testJustInTimeBindingsAreSharedWithParentIfPossible() { Injector parent = Guice.createInjector(); Injector child = parent.createChildInjector(); assertSame(child.getInstance(A.class), parent.getInstance(A.class)); Injector anotherChild = parent.createChildInjector(); assertSame(anotherChild.getInstance(A.class), parent.getInstance(A.class)); Injector grandchild = child.createChildInjector(); assertSame(grandchild.getInstance(A.class), parent.getInstance(A.class)); } public void testBindingsInherited() { Injector parent = Guice.createInjector(bindsB); Injector child = parent.createChildInjector(); assertSame(RealB.class, child.getInstance(B.class).getClass()); } public void testGetParent() { Injector top = Guice.createInjector(bindsA); Injector middle = top.createChildInjector(bindsB); Injector bottom = middle.createChildInjector(); assertSame(middle, bottom.getParent()); assertSame(top, middle.getParent()); assertNull(top.getParent()); } public void testChildBindingsNotVisibleToParent() { Injector parent = Guice.createInjector(); parent.createChildInjector(bindsB); try { parent.getBinding(B.class); fail(); } catch (ConfigurationException expected) { } } public void testScopesInherited() { Injector parent = Guice.createInjector(new AbstractModule() { protected void configure() { bindScope(MyScope.class, Scopes.SINGLETON); } }); Injector child = parent.createChildInjector(new AbstractModule() { @Override protected void configure() { bind(A.class).in(MyScope.class); } }); assertSame(child.getInstance(A.class), child.getInstance(A.class)); } /*if[AOP]*/ private final org.aopalliance.intercept.MethodInterceptor returnNullInterceptor = new org.aopalliance.intercept.MethodInterceptor() { public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) { return null; } }; public void testInterceptorsInherited() { Injector parent = Guice.createInjector(new AbstractModule() { protected void configure() { super.bindInterceptor(Matchers.any(), Matchers.returns(Matchers.identicalTo(A.class)), returnNullInterceptor); } }); Injector child = parent.createChildInjector(new AbstractModule() { protected void configure() { bind(C.class); } }); assertNull(child.getInstance(C.class).interceptedMethod()); } /*end[AOP]*/ public void testTypeConvertersInherited() { Injector parent = Guice.createInjector(bindListConverterModule); Injector child = parent.createChildInjector(bindStringNamedB); assertEquals(ImmutableList.of(), child.getInstance(Key.get(List.class, Names.named("B")))); } public void testTypeConvertersConflicting() { Injector parent = Guice.createInjector(bindListConverterModule); Injector child = parent.createChildInjector(bindListConverterModule, bindStringNamedB); try { child.getInstance(Key.get(List.class, Names.named("B"))); fail(); } catch (ConfigurationException expected) { Asserts.assertContains(expected.getMessage(), "Multiple converters can convert"); } } public void testInjectorInjectionSpanningInjectors() { Injector parent = Guice.createInjector(); Injector child = parent.createChildInjector(new AbstractModule() { protected void configure() { bind(D.class); } }); D d = child.getInstance(D.class); assertSame(d.injector, child); E e = child.getInstance(E.class); assertSame(e.injector, parent); } public void testSeveralLayersOfHierarchy() { Injector top = Guice.createInjector(bindsA); Injector left = top.createChildInjector(); Injector leftLeft = left.createChildInjector(bindsD); Injector right = top.createChildInjector(bindsD); assertSame(leftLeft, leftLeft.getInstance(D.class).injector); assertSame(right, right.getInstance(D.class).injector); assertSame(top, leftLeft.getInstance(E.class).injector); assertSame(top.getInstance(A.class), leftLeft.getInstance(A.class)); Injector leftRight = left.createChildInjector(bindsD); assertSame(leftRight, leftRight.getInstance(D.class).injector); try { top.getInstance(D.class); fail(); } catch (ConfigurationException expected) { } try { left.getInstance(D.class); fail(); } catch (ConfigurationException expected) { } } public void testScopeBoundInChildInjectorOnly() { Injector parent = Guice.createInjector(); Injector child = parent.createChildInjector(new AbstractModule() { protected void configure() { bindScope(MyScope.class, Scopes.SINGLETON); } }); try { parent.getProvider(F.class); fail(); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "No scope is bound to com.google.inject.ParentInjectorTest$MyScope.", "at " + F.class.getName() + ".class(ParentInjectorTest.java", " while locating " + F.class.getName()); } assertNotNull(child.getProvider(F.class).get()); } public void testErrorInParentButOkayInChild() { Injector parent = Guice.createInjector(); Injector childInjector = parent.createChildInjector(new AbstractModule() { protected void configure() { bindScope(MyScope.class, Scopes.SINGLETON); bind(Object.class).to(F.class); } }); Object one = childInjector.getInstance(Object.class); Object two = childInjector.getInstance(Object.class); assertSame(one, two); } public void testErrorInParentAndChild() { Injector parent = Guice.createInjector(); Injector childInjector = parent.createChildInjector(); try { childInjector.getInstance(G.class); fail(); } catch(ConfigurationException expected) { assertContains(expected.getMessage(), "No scope is bound to " + MyScope.class.getName(), "at " + F.class.getName() + ".class(ParentInjectorTest.java:", " while locating " + G.class.getName()); } } @Singleton static class A {} private final Module bindsA = new AbstractModule() { protected void configure() { bind(A.class).toInstance(new A()); } }; interface B {} static class RealB implements B {} private final Module bindsB = new AbstractModule() { protected void configure() { bind(B.class).to(RealB.class); } }; @Target(TYPE) @Retention(RUNTIME) @ScopeAnnotation public @interface MyScope {} private final TypeConverter listConverter = new TypeConverter() { public Object convert(String value, TypeLiteral toType) { return ImmutableList.of(); } }; private final Module bindListConverterModule = new AbstractModule() { protected void configure() { convertToTypes(Matchers.any(), listConverter); } }; private final Module bindStringNamedB = new AbstractModule() { protected void configure() { bind(String.class).annotatedWith(Names.named("B")).toInstance("buzz"); } }; public static class C { public A interceptedMethod() { return new A(); } } static class D { @Inject Injector injector; } static class E { @Inject Injector injector; } private final Module bindsD = new AbstractModule() { protected void configure() { bind(D.class); } }; @MyScope static class F implements G {} @ImplementedBy(F.class) interface G {} } guice-3.0/core/test/com/google/inject/RequestInjectionTest.java0000644000175000017500000001324511460132772024567 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertContains; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class RequestInjectionTest extends TestCase { @Retention(RUNTIME) @BindingAnnotation @interface ForField {} @Retention(RUNTIME) @BindingAnnotation @interface ForMethod {} protected void setUp() throws Exception { super.setUp(); HasInjections.staticField = 0; HasInjections.staticMethod = null; } public void testInjectMembers() { final HasInjections hi = new HasInjections(); Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(ForMethod.class).to("test"); bindConstant().annotatedWith(ForField.class).to(5); requestInjection(hi); } }); assertEquals("test", hi.instanceMethod); assertEquals(5, hi.instanceField); assertNull(HasInjections.staticMethod); assertEquals(0, HasInjections.staticField); } public void testInjectStatics() throws CreationException { Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(ForMethod.class).to("test"); bindConstant().annotatedWith(ForField.class).to(5); requestStaticInjection(HasInjections.class); } }); assertEquals("test", HasInjections.staticMethod); assertEquals(5, HasInjections.staticField); } public void testInjectMembersAndStatics() { final HasInjections hi = new HasInjections(); Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(ForMethod.class).to("test"); bindConstant().annotatedWith(ForField.class).to(5); requestStaticInjection(HasInjections.class); requestInjection(hi); } }); assertEquals("test", hi.instanceMethod); assertEquals(5, hi.instanceField); assertEquals("test", HasInjections.staticMethod); assertEquals(5, HasInjections.staticField); } public void testValidationErrorOnInjectedMembers() { try { Guice.createInjector(new AbstractModule() { protected void configure() { requestInjection(new NeedsRunnable()); } }); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) No implementation for java.lang.Runnable was bound", "at " + NeedsRunnable.class.getName(), ".runnable(RequestInjectionTest.java:"); } } public void testInjectionErrorOnInjectedMembers() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(Runnable.class).toProvider(new Provider() { public Runnable get() { throw new UnsupportedOperationException(); } }); requestInjection(new NeedsRunnable()); } }); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Error in custom provider, java.lang.UnsupportedOperationException", "for field at " + NeedsRunnable.class.getName() + ".runnable(RequestInjectionTest.java:", "at " + getClass().getName(), ".configure(RequestInjectionTest.java:"); } } public void testUserExceptionWhileInjectingInstance() { try { Guice.createInjector(new AbstractModule() { protected void configure() { requestInjection(new BlowsUpOnInject()); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Error injecting method, java.lang.UnsupportedOperationException: Pop", "at " + BlowsUpOnInject.class.getName() + ".injectInstance(RequestInjectionTest.java:"); } } public void testUserExceptionWhileInjectingStatically() { try { Guice.createInjector(new AbstractModule() { protected void configure() { requestStaticInjection(BlowsUpOnInject.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Error injecting method, java.lang.UnsupportedOperationException: Snap", "at " + BlowsUpOnInject.class.getName() + ".injectStatically(RequestInjectionTest.java:"); } } static class NeedsRunnable { @Inject Runnable runnable; } static class HasInjections { @Inject @ForField static int staticField; @Inject @ForField int instanceField; static String staticMethod; String instanceMethod; @Inject static void setStaticMethod(@ForMethod String staticMethod) { HasInjections.staticMethod = staticMethod; } @Inject void setInstanceS(@ForMethod String instanceS) { this.instanceMethod = instanceS; } } static class BlowsUpOnInject { @Inject void injectInstance() { throw new UnsupportedOperationException("Pop"); } @Inject static void injectStatically() { throw new UnsupportedOperationException("Snap"); } } } guice-3.0/core/test/com/google/inject/TypeLiteralTest.java0000644000175000017500000001710011473266150023526 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertEqualsBothWays; import static com.google.inject.Asserts.assertNotSerializable; import com.google.inject.internal.util.ImmutableList; import com.google.inject.util.Types; import java.io.IOException; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.List; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class TypeLiteralTest extends TestCase { public void testWithParameterizedType() { TypeLiteral> a = new TypeLiteral>() {}; TypeLiteral> b = new TypeLiteral>( Types.listOf(String.class)) {}; assertEqualsBothWays(a, b); } public void testEquality() { TypeLiteral> t1 = new TypeLiteral>() {}; TypeLiteral> t2 = new TypeLiteral>() {}; TypeLiteral> t3 = new TypeLiteral>() {}; TypeLiteral t4 = new TypeLiteral() {}; assertEqualsBothWays(t1, t2); assertFalse(t2.equals(t3)); assertFalse(t3.equals(t2)); assertFalse(t2.equals(t4)); assertFalse(t4.equals(t2)); TypeLiteral t5 = TypeLiteral.get(String.class); assertEqualsBothWays(t4, t5); } public List wildcardExtends; public void testWithWildcardType() throws NoSuchFieldException, IOException { TypeLiteral a = TypeLiteral.get(getClass().getField("wildcardExtends").getGenericType()); TypeLiteral b = TypeLiteral.get(Types.listOf(Types.subtypeOf(CharSequence.class))); TypeLiteral c = new TypeLiteral>() {}; assertEqualsBothWays(a, b); assertEqualsBothWays(b, c); assertEquals("java.util.List", a.toString()); assertEquals("java.util.List", b.toString()); assertEquals("java.util.List", c.toString()); assertNotSerializable(a); assertNotSerializable(b); assertNotSerializable(c); } public void testMissingTypeParameter() { try { new TypeLiteral() {}; fail(); } catch (RuntimeException e) { /* expected */ } } public void testTypesInvolvingArraysForEquality() { TypeLiteral stringArray = new TypeLiteral() {}; assertEquals(stringArray, new TypeLiteral() {}); TypeLiteral> listOfStringArray = new TypeLiteral>() {}; assertEquals(listOfStringArray, new TypeLiteral>() {}); } public void testEqualityOfGenericArrayAndClassArray() { TypeLiteral arrayAsClass = TypeLiteral.get(String[].class); TypeLiteral arrayAsType = new TypeLiteral() {}; assertEquals(arrayAsClass, arrayAsType); } public void testEqualityOfMultidimensionalGenericArrayAndClassArray() { TypeLiteral arrayAsClass = TypeLiteral.get(String[][][].class); TypeLiteral arrayAsType = new TypeLiteral() {}; assertEquals(arrayAsClass, arrayAsType); } public void testTypeLiteralsMustHaveRawTypes() { try { TypeLiteral.get(Types.subtypeOf(Runnable.class)); fail(); } catch (IllegalArgumentException expected) { Asserts.assertContains(expected.getMessage(), "Expected a Class, ParameterizedType, or " + "GenericArrayType, but is of type " + "com.google.inject.internal.MoreTypes$WildcardTypeImpl"); } } /** * Unlike Key, TypeLiteral retains full type information and differentiates * between {@code int.class} and {@code Integer.class}. */ public void testDifferentiationBetweenWrappersAndPrimitives() { Class[] primitives = new Class[] { boolean.class, byte.class, short.class, int.class, long.class, float.class, double.class, char.class, void.class }; Class[] wrappers = new Class[] { Boolean.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Character.class, Void.class }; for (int t = 0; t < primitives.length; t++) { @SuppressWarnings("unchecked") TypeLiteral primitiveTl = TypeLiteral.get(primitives[t]); @SuppressWarnings("unchecked") TypeLiteral wrapperTl = TypeLiteral.get(wrappers[t]); assertFalse(primitiveTl.equals(wrapperTl)); assertEquals(primitives[t], primitiveTl.getType()); assertEquals(wrappers[t], wrapperTl.getType()); assertEquals(primitives[t], primitiveTl.getRawType()); assertEquals(wrappers[t], wrapperTl.getRawType()); } } public void testSerialization() throws IOException { assertNotSerializable(new TypeLiteral>() {}); } public void testTypeVariableWithNoBound() { TypeVariable>[] typeVariables = HasTypeParameters.class.getTypeParameters(); TypeLiteral aTl = TypeLiteral.get(typeVariables[0]); assertEquals(Object.class, aTl.getRawType()); assertEquals("A", aTl.toString()); TypeVariable aTv = (TypeVariable) aTl.getType(); assertEquals(HasTypeParameters.class, aTv.getGenericDeclaration()); assertEquals("A", aTv.getName()); assertEquals(ImmutableList.of(Object.class), ImmutableList.of(aTv.getBounds())); assertEquals("A", aTv.toString()); assertEqualsBothWays(aTl, TypeLiteral.get(HasTypeParameters.class.getTypeParameters()[0])); } public void testTypeVariablesWithSingleBound() { TypeVariable>[] typeVariables = HasTypeParameters.class.getTypeParameters(); TypeLiteral cTl = TypeLiteral.get(typeVariables[2]); assertEquals(Object.class, cTl.getRawType()); assertEquals("C", cTl.toString()); TypeVariable cTv = (TypeVariable) cTl.getType(); assertEquals(HasTypeParameters.class, cTv.getGenericDeclaration()); assertEquals("C", cTv.getName()); assertEquals(ImmutableList.of(Runnable.class), ImmutableList.of(cTv.getBounds())); assertEquals("C", cTv.toString()); assertEqualsBothWays(cTl, TypeLiteral.get(HasTypeParameters.class.getTypeParameters()[2])); } public void testTypeVariableWithMultipleBounds() { TypeVariable>[] typeVariables = HasTypeParameters.class.getTypeParameters(); TypeLiteral bTl = TypeLiteral.get(typeVariables[1]); assertEquals(Object.class, bTl.getRawType()); assertEquals("B", bTl.toString()); TypeVariable bTv = (TypeVariable) bTl.getType(); assertEquals(HasTypeParameters.class, bTv.getGenericDeclaration()); assertEquals("B", bTv.getName()); assertEquals(ImmutableList.of(Types.listOf(typeVariables[0]), Runnable.class), ImmutableList.of(bTv.getBounds())); assertEquals("B", bTv.toString()); assertEqualsBothWays(bTl, TypeLiteral.get(HasTypeParameters.class.getTypeParameters()[1])); } class HasTypeParameters & Runnable, C extends Runnable> { A a; B b; C c; } } guice-3.0/core/test/com/google/inject/spi/0000755000175000017500000000000011531414174020355 5ustar drazzibdrazzibguice-3.0/core/test/com/google/inject/spi/ElementApplyToTest.java0000644000175000017500000000173511460132764024773 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Module; /** * @author jessewilson@google.com (Jesse Wilson) */ public class ElementApplyToTest extends ElementsTest { protected void checkModule(Module module, ElementVisitor... visitors) { // convert from module to elements and back super.checkModule(Elements.getModule(Elements.getElements(module)), visitors); } }guice-3.0/core/test/com/google/inject/spi/BindingTargetVisitorTest.java0000644000175000017500000000233111460132764026163 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Injector; import junit.framework.TestCase; /** * Simple little test that should compile. Ensures that wildcards on the * generics are correct. * * @author phopkins@gmail.com */ public class BindingTargetVisitorTest extends TestCase { public void testBindingTargetVisitorTypeTest() throws Exception { Injector injector = Guice.createInjector(); for (Binding binding : injector.getBindings().values()) { binding.acceptTargetVisitor(new DefaultBindingTargetVisitor() {}); } } } guice-3.0/core/test/com/google/inject/spi/HasDependenciesTest.java0000644000175000017500000000636511460132764025117 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Iterables; import java.util.Set; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class HasDependenciesTest extends TestCase { /** * When an instance implements HasDependencies, the injected dependencies aren't used. */ public void testInstanceWithDependencies() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(A.class).toInstance(new AWithDependencies()); } }); InstanceBinding binding = (InstanceBinding) injector.getBinding(A.class); assertEquals(ImmutableSet.>of(Dependency.get(Key.get(Integer.class))), binding.getDependencies()); } public void testInstanceWithoutDependencies() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(A.class).toInstance(new A()); } }); InstanceBinding binding = (InstanceBinding) injector.getBinding(A.class); Dependency onlyDependency = Iterables.getOnlyElement(binding.getDependencies()); assertEquals(Key.get(String.class), onlyDependency.getKey()); } public void testProvider() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(A.class).toProvider(new ProviderOfA()); } }); ProviderInstanceBinding binding = (ProviderInstanceBinding) injector.getBinding(A.class); Dependency onlyDependency = Iterables.getOnlyElement(binding.getDependencies()); assertEquals(Key.get(String.class), onlyDependency.getKey()); } static class A { @Inject void injectUnusedDependencies(String unused) {} } static class ProviderOfA implements Provider { @Inject void injectUnusedDependencies(String unused) {} public A get() { throw new UnsupportedOperationException(); } } static class AWithDependencies extends A implements HasDependencies { public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(Key.get(Integer.class))); } } static class ProviderOfAWithDependencies extends ProviderOfA implements ProviderWithDependencies { public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(Key.get(Integer.class))); } } } guice-3.0/core/test/com/google/inject/spi/FailingBindingScopingVisitor.java0000644000175000017500000000225411460132764026775 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Scope; import java.lang.annotation.Annotation; import junit.framework.AssertionFailedError; public class FailingBindingScopingVisitor implements BindingScopingVisitor { public Void visitEagerSingleton() { throw new AssertionFailedError(); } public Void visitScope(Scope scope) { throw new AssertionFailedError(); } public Void visitScopeAnnotation(Class scopeAnnotation) { throw new AssertionFailedError(); } public Void visitNoScoping() { throw new AssertionFailedError(); } }guice-3.0/core/test/com/google/inject/spi/ModuleRewriterTest.java0000644000175000017500000000715011460132764025037 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.AbstractModule; import com.google.inject.Binding; import com.google.inject.ConfigurationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.internal.util.Lists; import com.google.inject.name.Names; import java.util.List; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class ModuleRewriterTest extends TestCase { public void testRewriteBindings() { // create a module the binds String.class and CharSequence.class Module module = new AbstractModule() { protected void configure() { bind(String.class).toInstance("Pizza"); bind(CharSequence.class).toInstance("Wine"); } }; // record the elements from that module List elements = Elements.getElements(module); // create a rewriter that rewrites the binding to 'Wine' with a binding to 'Beer' List rewritten = Lists.newArrayList(); for (Element element : elements) { element = element.acceptVisitor(new DefaultElementVisitor() { @Override public Element visit(Binding binding) { T target = binding.acceptTargetVisitor(Elements.getInstanceVisitor()); if ("Wine".equals(target)) { return null; } else { return binding; } } }); if (element != null) { rewritten.add(element); } } // create a module from the original list of elements and the rewriter Module rewrittenModule = Elements.getModule(rewritten); // the wine binding is dropped Injector injector = Guice.createInjector(rewrittenModule); try { injector.getInstance(CharSequence.class); fail(); } catch (ConfigurationException expected) { } } public void testGetProviderAvailableAtInjectMembersTime() { Module module = new AbstractModule() { public void configure() { final Provider stringProvider = getProvider(String.class); bind(String.class).annotatedWith(Names.named("2")).toProvider(new Provider() { private String value; @Inject void initialize() { value = stringProvider.get(); } public String get() { return value; } }); bind(String.class).toInstance("A"); } }; // the module works fine normally Injector injector = Guice.createInjector(module); assertEquals("A", injector.getInstance(Key.get(String.class, Names.named("2")))); // and it should also work fine if we rewrite it List elements = Elements.getElements(module); Module replayed = Elements.getModule(elements); Injector replayedInjector = Guice.createInjector(replayed); assertEquals("A", replayedInjector.getInstance(Key.get(String.class, Names.named("2")))); } } guice-3.0/core/test/com/google/inject/spi/InjectionPointTest.java0000644000175000017500000003270111460132764025022 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import static com.google.inject.Asserts.assertContains; import static com.google.inject.Asserts.assertEqualsBothWays; import static com.google.inject.Asserts.assertNotSerializable; import com.google.inject.ConfigurationException; import com.google.inject.Inject; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.internal.ErrorsException; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import static com.google.inject.internal.util.Iterables.getOnlyElement; import com.google.inject.name.Named; import static com.google.inject.name.Names.named; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import junit.framework.Assert; import junit.framework.TestCase; import com.google.inject.spi.InjectionPoint.Signature; /** * @author jessewilson@google.com (Jesse Wilson) */ public class InjectionPointTest extends TestCase { public @Inject @Named("a") String foo; public @Inject void bar(@Named("b") String param) {} public static class Constructable { @Inject public Constructable(@Named("c") String param) {} } public void testFieldInjectionPoint() throws NoSuchFieldException, IOException, ErrorsException { TypeLiteral typeLiteral = TypeLiteral.get(getClass()); Field fooField = getClass().getField("foo"); InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, fooField, false); assertSame(fooField, injectionPoint.getMember()); assertFalse(injectionPoint.isOptional()); assertEquals(getClass().getName() + ".foo", injectionPoint.toString()); assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, fooField, false)); assertNotSerializable(injectionPoint); Dependency dependency = getOnlyElement(injectionPoint.getDependencies()); assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=a)]@" + getClass().getName() + ".foo", dependency.toString()); assertEquals(fooField, dependency.getInjectionPoint().getMember()); assertEquals(-1, dependency.getParameterIndex()); Assert.assertEquals(Key.get(String.class, named("a")), dependency.getKey()); assertEquals(false, dependency.isNullable()); assertNotSerializable(dependency); assertEqualsBothWays(dependency, getOnlyElement(new InjectionPoint(typeLiteral, fooField, false).getDependencies())); } public void testMethodInjectionPoint() throws Exception { TypeLiteral typeLiteral = TypeLiteral.get(getClass()); Method barMethod = getClass().getMethod("bar", String.class); InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, barMethod, false); assertSame(barMethod, injectionPoint.getMember()); assertFalse(injectionPoint.isOptional()); assertEquals(getClass().getName() + ".bar()", injectionPoint.toString()); assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, barMethod, false)); assertNotSerializable(injectionPoint); Dependency dependency = getOnlyElement(injectionPoint.getDependencies()); assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=b)]@" + getClass().getName() + ".bar()[0]", dependency.toString()); assertEquals(barMethod, dependency.getInjectionPoint().getMember()); assertEquals(0, dependency.getParameterIndex()); assertEquals(Key.get(String.class, named("b")), dependency.getKey()); assertEquals(false, dependency.isNullable()); assertNotSerializable(dependency); assertEqualsBothWays(dependency, getOnlyElement(new InjectionPoint(typeLiteral, barMethod, false).getDependencies())); } public void testConstructorInjectionPoint() throws NoSuchMethodException, IOException, ErrorsException { TypeLiteral typeLiteral = TypeLiteral.get(Constructable.class); Constructor constructor = Constructable.class.getConstructor(String.class); InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, constructor); assertSame(constructor, injectionPoint.getMember()); assertFalse(injectionPoint.isOptional()); assertEquals(Constructable.class.getName() + ".()", injectionPoint.toString()); assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, constructor)); assertNotSerializable(injectionPoint); Dependency dependency = getOnlyElement(injectionPoint.getDependencies()); assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=c)]@" + Constructable.class.getName() + ".()[0]", dependency.toString()); assertEquals(constructor, dependency.getInjectionPoint().getMember()); assertEquals(0, dependency.getParameterIndex()); assertEquals(Key.get(String.class, named("c")), dependency.getKey()); assertEquals(false, dependency.isNullable()); assertNotSerializable(dependency); assertEqualsBothWays(dependency, getOnlyElement(new InjectionPoint(typeLiteral, constructor).getDependencies())); } public void testUnattachedDependency() throws IOException { Dependency dependency = Dependency.get(Key.get(String.class, named("d"))); assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=d)]", dependency.toString()); assertNull(dependency.getInjectionPoint()); assertEquals(-1, dependency.getParameterIndex()); assertEquals(Key.get(String.class, named("d")), dependency.getKey()); assertEquals(true, dependency.isNullable()); assertNotSerializable(dependency); assertEqualsBothWays(dependency, Dependency.get(Key.get(String.class, named("d")))); } public void testForConstructor() throws NoSuchMethodException { Constructor constructor = HashSet.class.getConstructor(); TypeLiteral> hashSet = new TypeLiteral>() {}; InjectionPoint injectionPoint = InjectionPoint.forConstructor(constructor, hashSet); assertSame(constructor, injectionPoint.getMember()); assertEquals(ImmutableList.of(), injectionPoint.getDependencies()); assertFalse(injectionPoint.isOptional()); try { InjectionPoint.forConstructor(constructor, new TypeLiteral>() {}); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "java.util.LinkedHashSet", " does not define java.util.HashSet.()", " while locating java.util.LinkedHashSet"); } try { InjectionPoint.forConstructor((Constructor) constructor, new TypeLiteral>() {}); } catch (ConfigurationException expected) { assertContains(expected.getMessage(), "java.util.Set", " does not define java.util.HashSet.()", " while locating java.util.Set"); } } public void testForConstructorOf() { InjectionPoint injectionPoint = InjectionPoint.forConstructorOf(Constructable.class); assertEquals(Constructable.class.getName() + ".()", injectionPoint.toString()); } public void testAddForInstanceMethodsAndFields() throws Exception { Method instanceMethod = HasInjections.class.getMethod("instanceMethod", String.class); Field instanceField = HasInjections.class.getField("instanceField"); TypeLiteral type = TypeLiteral.get(HasInjections.class); assertEquals(ImmutableSet.of( new InjectionPoint(type, instanceMethod, false), new InjectionPoint(type, instanceField, false)), InjectionPoint.forInstanceMethodsAndFields(HasInjections.class)); } public void testAddForStaticMethodsAndFields() throws Exception { Method staticMethod = HasInjections.class.getMethod("staticMethod", String.class); Field staticField = HasInjections.class.getField("staticField"); Set injectionPoints = InjectionPoint.forStaticMethodsAndFields( HasInjections.class); assertEquals(ImmutableSet.of( new InjectionPoint(TypeLiteral.get(HasInjections.class), staticMethod, false), new InjectionPoint(TypeLiteral.get(HasInjections.class), staticField, false)), injectionPoints); } static class HasInjections { @Inject public static void staticMethod(@Named("a") String a) {} @Inject @Named("c") public static String staticField; @Inject public void instanceMethod(@Named("d") String d) {} @Inject @Named("f") public String instanceField; } public void testAddForParameterizedInjections() { TypeLiteral type = new TypeLiteral>() {}; InjectionPoint constructor = InjectionPoint.forConstructorOf(type); assertEquals(new Key>() {}, getOnlyElement(constructor.getDependencies()).getKey()); InjectionPoint field = getOnlyElement(InjectionPoint.forInstanceMethodsAndFields(type)); assertEquals(new Key>() {}, getOnlyElement(field.getDependencies()).getKey()); } static class ParameterizedInjections { @Inject Set setOfTees; @Inject public ParameterizedInjections(Map map) {} } public void testSignature() throws Exception { Signature fooA = new Signature(Foo.class.getDeclaredMethod( "a", String.class, int.class)); Signature fooB = new Signature(Foo.class.getDeclaredMethod("b")); Signature barA = new Signature(Bar.class.getDeclaredMethod( "a", String.class, int.class)); Signature barB = new Signature(Bar.class.getDeclaredMethod("b")); assertEquals(fooA.hashCode(), barA.hashCode()); assertEquals(fooB.hashCode(), barB.hashCode()); assertEquals(fooA, barA); assertEquals(fooB, barB); } static class Foo { void a(String s, int i) {} int b() { return 0; } } static class Bar { public void a(String s, int i) {} void b() {} } public void testOverrideBehavior() { Set points; points = InjectionPoint.forInstanceMethodsAndFields(Super.class); assertEquals(points.toString(), 6, points.size()); assertPoints(points, Super.class, "atInject", "gInject", "privateAtAndPublicG", "privateGAndPublicAt", "atFirstThenG", "gFirstThenAt"); points = InjectionPoint.forInstanceMethodsAndFields(Sub.class); assertEquals(points.toString(), 7, points.size()); // Superclass will always have is private members injected, // and 'gInject' was last @Injected in Super, so that remains the owner assertPoints(points, Super.class, "privateAtAndPublicG", "privateGAndPublicAt", "gInject"); // Subclass also has the "private" methods, but they do not override // the superclass' methods, and it now owns the inject2 methods. assertPoints(points, Sub.class, "privateAtAndPublicG", "privateGAndPublicAt", "atFirstThenG", "gFirstThenAt"); points = InjectionPoint.forInstanceMethodsAndFields(SubSub.class); assertEquals(points.toString(), 6, points.size()); // Superclass still has all the injection points it did before.. assertPoints(points, Super.class, "privateAtAndPublicG", "privateGAndPublicAt", "gInject"); // Subclass is missing the privateGAndPublicAt because it first became public with // javax.inject.Inject and was overrode without an annotation, which means it // disappears. (It was guice @Inject in Super, but it was private there, so it doesn't // effect the annotations of the subclasses.) assertPoints(points, Sub.class, "privateAtAndPublicG", "atFirstThenG", "gFirstThenAt"); } private void assertPoints(Iterable points, Class clazz, String... methodNames) { Set methods = new HashSet(); for(InjectionPoint point : points) { if(point.getDeclaringType().getRawType() == clazz) { methods.add(point.getMember().getName()); } } assertEquals(points.toString(), ImmutableSet.of(methodNames), methods); } static class Super { @javax.inject.Inject public void atInject() {} @com.google.inject.Inject public void gInject() {} @javax.inject.Inject private void privateAtAndPublicG() {} @com.google.inject.Inject private void privateGAndPublicAt() {} @javax.inject.Inject public void atFirstThenG() {} @com.google.inject.Inject public void gFirstThenAt() {} } static class Sub extends Super { public void atInject() {} public void gInject() {} @com.google.inject.Inject public void privateAtAndPublicG() {} @javax.inject.Inject public void privateGAndPublicAt() {} @com.google.inject.Inject public void atFirstThenG() {} @javax.inject.Inject public void gFirstThenAt() {} } static class SubSub extends Sub { public void privateAtAndPublicG() {} public void privateGAndPublicAt() {} public void atFirstThenG() {} public void gFirstThenAt() {} } } guice-3.0/core/test/com/google/inject/spi/InjectorSpiTest.java0000644000175000017500000000603511460132764024320 0ustar drazzibdrazzibpackage com.google.inject.spi; import java.util.Map; import com.google.inject.AbstractModule; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import junit.framework.TestCase; /** * @author sberlin@gmail.com (Sam Berlin) */ public class InjectorSpiTest extends TestCase { public void testExistingBinding() { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Foo.class); bind(Baz.class); } }); // Sanity check -- ensure we return the proper binding for all existing bindings. for(Map.Entry, Binding> entry : injector.getAllBindings().entrySet()) { assertSame(entry.getValue(), injector.getExistingBinding(entry.getKey())); } // Now run through specifics... Binding binding; // 1) non-Provider Foo.class binding = injector.getExistingBinding(Key.get(Foo.class)); assertNotNull(binding); assertEquals(Foo.class, binding.getKey().getTypeLiteral().getRawType()); // 2) Provider class (should already exist, because Baz @Injects it). // the assertTrue is a bit stricter than necessary, but makes sure this works for pre-existing Provider bindings assertTrue(injector.getAllBindings().containsKey(Key.get(new TypeLiteral>() {}))); binding = injector.getExistingBinding(Key.get(new TypeLiteral>() {})); assertNotNull(binding); assertEquals(Provider.class, binding.getKey().getTypeLiteral().getRawType()); assertEquals(Foo.class, ((Provider)binding.getProvider().get()).get().getClass()); // 3) non-Provider Baz.class binding = injector.getExistingBinding(Key.get(Baz.class)); assertNotNull(binding); assertEquals(Baz.class, binding.getKey().getTypeLiteral().getRawType()); // 4) Provider class (should not already exist, because nothing used it yet). // the assertFalse is a bit stricter than necessary, but makes sure this works for non-pre-existing Provider bindings assertFalse(injector.getAllBindings().containsKey(Key.get(new TypeLiteral>() {}))); binding = injector.getExistingBinding(Key.get(new TypeLiteral>() {})); assertNotNull(binding); assertEquals(Provider.class, binding.getKey().getTypeLiteral().getRawType()); assertEquals(Baz.class, ((Provider)binding.getProvider().get()).get().getClass()); // 5) non-Provider Bar, doesn't exist. assertNull(injector.getExistingBinding(Key.get(Bar.class))); // 6) Provider Bar, doesn't exist. assertNull(injector.getExistingBinding(Key.get(new TypeLiteral>() {}))); } private static class Foo {} private static class Bar {} private static class Baz { @SuppressWarnings("unused") @Inject Provider fooP; } } guice-3.0/core/test/com/google/inject/spi/ElementsTest.java0000644000175000017500000012556111461077476023662 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.AbstractModule; import static com.google.inject.Asserts.assertContains; import com.google.inject.Binding; import com.google.inject.BindingAnnotation; import com.google.inject.Inject; import com.google.inject.Key; import com.google.inject.MembersInjector; import com.google.inject.Module; import com.google.inject.PrivateBinder; import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.Scopes; import com.google.inject.Singleton; import com.google.inject.Stage; import com.google.inject.TypeLiteral; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.binder.AnnotatedConstantBindingBuilder; import com.google.inject.binder.ConstantBindingBuilder; import com.google.inject.binder.ScopedBindingBuilder; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.ImmutableSet; import static com.google.inject.internal.util.Iterables.getOnlyElement; import com.google.inject.matcher.Matcher; import com.google.inject.matcher.Matchers; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.util.Providers; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class ElementsTest extends TestCase { // Binder fidelity tests public void testAddMessageErrorCommand() { checkModule( new AbstractModule() { protected void configure() { addError("Message %s %d %s", "A", 5, "C"); } }, new FailingElementVisitor() { @Override public Void visit(Message command) { assertEquals("Message A 5 C", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSources().toString(), ElementsTest.class.getName(), ".configure(ElementsTest.java:"); assertContains(command.getSource(), "ElementsTest.java"); return null; } } ); } public void testAddThrowableErrorCommand() { checkModule( new AbstractModule() { protected void configure() { addError(new Exception("A")); } }, new FailingElementVisitor() { @Override public Void visit(Message command) { assertEquals("A", command.getCause().getMessage()); assertEquals(command.getMessage(), "An exception was caught and reported. Message: A"); assertContains(command.getSource(), "ElementsTest.java"); return null; } } ); } public void testErrorsAddedWhenExceptionsAreThrown() { checkModule( new AbstractModule() { protected void configure() { install(new AbstractModule() { protected void configure() { throw new RuntimeException("Throwing RuntimeException in AbstractModule.configure()."); } }); addError("Code after the exception still gets executed"); } }, new FailingElementVisitor() { @Override public Void visit(Message command) { assertEquals("Throwing RuntimeException in AbstractModule.configure().", command.getCause().getMessage()); return null; } }, new FailingElementVisitor() { @Override public Void visit(Message command) { assertEquals("Code after the exception still gets executed", command.getMessage()); return null; } } ); } private T getInstance(Binding binding) { return binding.acceptTargetVisitor(Elements.getInstanceVisitor()); } public void testBindConstantAnnotations() { checkModule( new AbstractModule() { protected void configure() { bindConstant().annotatedWith(SampleAnnotation.class).to("A"); bindConstant().annotatedWith(Names.named("Bee")).to("B"); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey()); assertEquals("A", getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(String.class, Names.named("Bee")), command.getKey()); assertEquals("B", getInstance(command)); return null; } } ); } public void testBindConstantTypes() { checkModule( new AbstractModule() { protected void configure() { bindConstant().annotatedWith(Names.named("String")).to("A"); bindConstant().annotatedWith(Names.named("int")).to(2); bindConstant().annotatedWith(Names.named("long")).to(3L); bindConstant().annotatedWith(Names.named("boolean")).to(false); bindConstant().annotatedWith(Names.named("double")).to(5.0d); bindConstant().annotatedWith(Names.named("float")).to(6.0f); bindConstant().annotatedWith(Names.named("short")).to((short) 7); bindConstant().annotatedWith(Names.named("char")).to('h'); bindConstant().annotatedWith(Names.named("byte")).to((byte) 8); bindConstant().annotatedWith(Names.named("Class")).to(Iterator.class); bindConstant().annotatedWith(Names.named("Enum")).to(CoinSide.TAILS); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(String.class, Names.named("String")), command.getKey()); assertEquals("A", getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Integer.class, Names.named("int")), command.getKey()); assertEquals(2, getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Long.class, Names.named("long")), command.getKey()); assertEquals(3L, getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Boolean.class, Names.named("boolean")), command.getKey()); assertEquals(false, getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Double.class, Names.named("double")), command.getKey()); assertEquals(5.0d, getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Float.class, Names.named("float")), command.getKey()); assertEquals(6.0f, getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Short.class, Names.named("short")), command.getKey()); assertEquals((short) 7, getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Character.class, Names.named("char")), command.getKey()); assertEquals('h', getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Byte.class, Names.named("byte")), command.getKey()); assertEquals((byte) 8, getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(Class.class, Names.named("Class")), command.getKey()); assertEquals(Iterator.class, getInstance(command)); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(CoinSide.class, Names.named("Enum")), command.getKey()); assertEquals(CoinSide.TAILS, getInstance(command)); return null; } } ); } public void testBindKeysNoAnnotations() { FailingElementVisitor keyChecker = new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(String.class), command.getKey()); return null; } }; checkModule( new AbstractModule() { protected void configure() { bind(String.class).toInstance("A"); bind(new TypeLiteral() {}).toInstance("B"); bind(Key.get(String.class)).toInstance("C"); } }, keyChecker, keyChecker, keyChecker ); } public void testBindKeysWithAnnotationType() { FailingElementVisitor annotationChecker = new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey()); return null; } }; checkModule( new AbstractModule() { protected void configure() { bind(String.class).annotatedWith(SampleAnnotation.class).toInstance("A"); bind(new TypeLiteral() {}).annotatedWith(SampleAnnotation.class).toInstance("B"); } }, annotationChecker, annotationChecker ); } public void testBindKeysWithAnnotationInstance() { FailingElementVisitor annotationChecker = new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(String.class, Names.named("a")), command.getKey()); return null; } }; checkModule( new AbstractModule() { protected void configure() { bind(String.class).annotatedWith(Names.named("a")).toInstance("B"); bind(new TypeLiteral() {}).annotatedWith(Names.named("a")).toInstance("C"); } }, annotationChecker, annotationChecker ); } public void testBindToProvider() { final Provider aProvider = new Provider() { public String get() { return "A"; } }; checkModule( new AbstractModule() { protected void configure() { bind(String.class).toProvider(aProvider); bind(List.class).toProvider(ListProvider.class); bind(Collection.class).toProvider(Key.get(ListProvider.class)); bind(Iterable.class).toProvider(new TypeLiteral>() {}); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof ProviderInstanceBinding); assertEquals(Key.get(String.class), command.getKey()); command.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit( ProviderInstanceBinding binding) { assertSame(aProvider, binding.getProviderInstance()); return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof ProviderKeyBinding); assertEquals(Key.get(List.class), command.getKey()); command.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(ProviderKeyBinding binding) { assertEquals(Key.get(ListProvider.class), binding.getProviderKey()); return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof ProviderKeyBinding); assertEquals(Key.get(Collection.class), command.getKey()); command.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(ProviderKeyBinding binding) { assertEquals(Key.get(ListProvider.class), binding.getProviderKey()); return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof ProviderKeyBinding); assertEquals(Key.get(Iterable.class), command.getKey()); command.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(ProviderKeyBinding binding) { assertEquals(new Key>() {}, binding.getProviderKey()); return null; } }); return null; } } ); } public void testBindToLinkedBinding() { checkModule( new AbstractModule() { protected void configure() { bind(List.class).to(ArrayList.class); bind(Map.class).to(new TypeLiteral>() {}); bind(Set.class).to(Key.get(TreeSet.class, SampleAnnotation.class)); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof LinkedKeyBinding); assertEquals(Key.get(List.class), command.getKey()); command.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(LinkedKeyBinding binding) { assertEquals(Key.get(ArrayList.class), binding.getLinkedKey()); return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof LinkedKeyBinding); assertEquals(Key.get(Map.class), command.getKey()); command.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(LinkedKeyBinding binding) { assertEquals(Key.get(new TypeLiteral>() {}), binding.getLinkedKey()); return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof LinkedKeyBinding); assertEquals(Key.get(Set.class), command.getKey()); command.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(LinkedKeyBinding binding) { assertEquals(Key.get(TreeSet.class, SampleAnnotation.class), binding.getLinkedKey()); return null; } }); return null; } } ); } public void testBindToInstance() { checkModule( new AbstractModule() { protected void configure() { bind(String.class).toInstance("A"); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertTrue(command instanceof InstanceBinding); assertEquals(Key.get(String.class), command.getKey()); assertEquals("A", getInstance(command)); return null; } } ); } public void testBindInScopes() { checkModule( new AbstractModule() { protected void configure() { bind(String.class); bind(List.class).to(ArrayList.class).in(Scopes.SINGLETON); bind(Map.class).to(HashMap.class).in(Singleton.class); bind(Set.class).to(TreeSet.class).asEagerSingleton(); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(String.class), command.getKey()); command.acceptScopingVisitor(new FailingBindingScopingVisitor() { @Override public Void visitNoScoping() { return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(List.class), command.getKey()); command.acceptScopingVisitor(new FailingBindingScopingVisitor() { @Override public Void visitScope(Scope scope) { assertEquals(Scopes.SINGLETON, scope); return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(Map.class), command.getKey()); command.acceptScopingVisitor(new FailingBindingScopingVisitor() { @Override public Void visitScopeAnnotation(Class annotation) { assertEquals(Singleton.class, annotation); return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(Set.class), command.getKey()); command.acceptScopingVisitor(new FailingBindingScopingVisitor() { public Void visitEagerSingleton() { return null; } }); return null; } } ); } public void testBindToInstanceInScope() { checkModule( new AbstractModule() { protected void configure() { AnnotatedBindingBuilder b = bind(String.class); b.toInstance("A"); b.in(Singleton.class); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { return null; } }, new FailingElementVisitor() { @Override public Void visit(Message command) { assertEquals("Setting the scope is not permitted when binding to a single instance.", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSource(), "ElementsTest.java"); return null; } } ); } public void testBindToInstanceScope() { checkModule( new AbstractModule() { protected void configure() { bind(String.class).toInstance("A"); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertEquals(Key.get(String.class), binding.getKey()); binding.acceptScopingVisitor(new FailingBindingScopingVisitor() { public Void visitEagerSingleton() { return null; } }); return null; } } ); } /*if[AOP]*/ public void testBindIntercepor() { final Matcher classMatcher = Matchers.subclassesOf(List.class); final Matcher methodMatcher = Matchers.any(); final org.aopalliance.intercept.MethodInterceptor methodInterceptor = new org.aopalliance.intercept.MethodInterceptor() { public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) { return null; } }; checkModule( new AbstractModule() { protected void configure() { bindInterceptor(classMatcher, methodMatcher, methodInterceptor); } }, new FailingElementVisitor() { @Override public Void visit(InterceptorBinding command) { assertSame(classMatcher, command.getClassMatcher()); assertSame(methodMatcher, command.getMethodMatcher()); assertEquals(Arrays.asList(methodInterceptor), command.getInterceptors()); return null; } } ); } /*end[AOP]*/ public void testBindScope() { checkModule( new AbstractModule() { protected void configure() { bindScope(SampleAnnotation.class, Scopes.NO_SCOPE); } }, new FailingElementVisitor() { @Override public Void visit(ScopeBinding command) { assertSame(SampleAnnotation.class, command.getAnnotationType()); assertSame(Scopes.NO_SCOPE, command.getScope()); return null; } } ); } public void testBindListener() { final Matcher typeMatcher = Matchers.only(TypeLiteral.get(String.class)); final TypeListener listener = new TypeListener() { public void hear(TypeLiteral type, TypeEncounter encounter) { throw new UnsupportedOperationException(); } }; checkModule( new AbstractModule() { protected void configure() { bindListener(typeMatcher, listener); } }, new FailingElementVisitor() { @Override public Void visit(TypeListenerBinding binding) { assertSame(typeMatcher, binding.getTypeMatcher()); assertSame(listener, binding.getListener()); return null; } } ); } public void testConvertToTypes() { final TypeConverter typeConverter = new TypeConverter() { public Object convert(String value, TypeLiteral toType) { return value; } }; checkModule( new AbstractModule() { protected void configure() { convertToTypes(Matchers.any(), typeConverter); } }, new FailingElementVisitor() { @Override public Void visit(TypeConverterBinding command) { assertSame(typeConverter, command.getTypeConverter()); assertSame(Matchers.any(), command.getTypeMatcher()); return null; } } ); } public void testGetProvider() { checkModule( new AbstractModule() { protected void configure() { Provider keyGetProvider = getProvider(Key.get(String.class, SampleAnnotation.class)); try { keyGetProvider.get(); } catch (IllegalStateException e) { assertEquals("This Provider cannot be used until the Injector has been created.", e.getMessage()); } Provider typeGetProvider = getProvider(String.class); try { typeGetProvider.get(); } catch (IllegalStateException e) { assertEquals("This Provider cannot be used until the Injector has been created.", e.getMessage()); } } }, new FailingElementVisitor() { @Override public Void visit(ProviderLookup command) { assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey()); assertNull(command.getDelegate()); return null; } }, new FailingElementVisitor() { @Override public Void visit(ProviderLookup command) { assertEquals(Key.get(String.class), command.getKey()); assertNull(command.getDelegate()); return null; } } ); } public void testElementInitialization() { final AtomicReference> providerFromBinder = new AtomicReference>(); final AtomicReference> membersInjectorFromBinder = new AtomicReference>(); final AtomicReference lastInjected = new AtomicReference(); final MembersInjector stringInjector = new MembersInjector() { public void injectMembers(String instance) { lastInjected.set(instance); } }; checkModule( new AbstractModule() { protected void configure() { providerFromBinder.set(getProvider(String.class)); membersInjectorFromBinder.set(getMembersInjector(String.class)); } }, new FailingElementVisitor() { public Void visit(ProviderLookup providerLookup) { @SuppressWarnings("unchecked") // we know that T is a String here ProviderLookup stringLookup = (ProviderLookup) providerLookup; stringLookup.initializeDelegate(Providers.of("out")); assertEquals("out", providerFromBinder.get().get()); return null; } }, new FailingElementVisitor() { @Override public Void visit(MembersInjectorLookup lookup) { @SuppressWarnings("unchecked") // we know that T is a String here MembersInjectorLookup stringLookup = (MembersInjectorLookup) lookup; stringLookup.initializeDelegate(stringInjector); membersInjectorFromBinder.get().injectMembers("in"); assertEquals("in", lastInjected.get()); return null; } }); } public void testGetMembersInjector() { checkModule( new AbstractModule() { protected void configure() { MembersInjector> typeMembersInjector = getMembersInjector(new TypeLiteral>() {}); try { typeMembersInjector.injectMembers(new A()); } catch (IllegalStateException e) { assertEquals( "This MembersInjector cannot be used until the Injector has been created.", e.getMessage()); } MembersInjector classMembersInjector = getMembersInjector(String.class); try { classMembersInjector.injectMembers("hello"); } catch (IllegalStateException e) { assertEquals( "This MembersInjector cannot be used until the Injector has been created.", e.getMessage()); } } }, new FailingElementVisitor() { @Override public Void visit(MembersInjectorLookup command) { assertEquals(new TypeLiteral>() {}, command.getType()); assertNull(command.getDelegate()); return null; } }, new FailingElementVisitor() { @Override public Void visit(MembersInjectorLookup command) { assertEquals(TypeLiteral.get(String.class), command.getType()); assertNull(command.getDelegate()); return null; } } ); } public void testRequestInjection() { final Object firstObject = new Object(); final Object secondObject = new Object(); checkModule( new AbstractModule() { protected void configure() { requestInjection(firstObject); requestInjection(secondObject); } }, new FailingElementVisitor() { @Override public Void visit(InjectionRequest command) { assertEquals(firstObject, command.getInstance()); return null; } }, new FailingElementVisitor() { @Override public Void visit(InjectionRequest command) { assertEquals(secondObject, command.getInstance()); return null; } } ); } public void testRequestStaticInjection() { checkModule( new AbstractModule() { protected void configure() { requestStaticInjection(ArrayList.class); } }, new FailingElementVisitor() { @Override public Void visit(StaticInjectionRequest command) { assertEquals(ArrayList.class, command.getType()); return null; } } ); } public void testNewPrivateBinder() { final Key collection = Key.get(Collection.class, SampleAnnotation.class); final Key arrayList = Key.get(ArrayList.class); final ImmutableSet> collections = ImmutableSet.>of(arrayList, collection); final Key a = Key.get(String.class, Names.named("a")); final Key b = Key.get(String.class, Names.named("b")); final ImmutableSet> ab = ImmutableSet.of(a, b); checkModule( new AbstractModule() { protected void configure() { PrivateBinder one = binder().newPrivateBinder(); one.expose(ArrayList.class); one.expose(Collection.class).annotatedWith(SampleAnnotation.class); one.bind(List.class).to(ArrayList.class); PrivateBinder two = binder().withSource("1 ElementsTest.java") .newPrivateBinder().withSource("2 ElementsTest.java"); two.expose(String.class).annotatedWith(Names.named("a")); two.expose(b); two.bind(List.class).to(ArrayList.class); } }, new FailingElementVisitor() { @Override public Void visit(PrivateElements one) { assertEquals(collections, one.getExposedKeys()); checkElements(one.getElements(), new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertEquals(Key.get(List.class), binding.getKey()); return null; } } ); return null; } }, new FailingElementVisitor() { @Override public Void visit(PrivateElements two) { assertEquals(ab, two.getExposedKeys()); assertEquals("1 ElementsTest.java", two.getSource()); checkElements(two.getElements(), new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertEquals("2 ElementsTest.java", binding.getSource()); assertEquals(Key.get(List.class), binding.getKey()); return null; } } ); return null; } } ); } public void testBindWithMultipleAnnotationsAddsError() { checkModule( new AbstractModule() { protected void configure() { AnnotatedBindingBuilder abb = bind(String.class); abb.annotatedWith(SampleAnnotation.class); abb.annotatedWith(Names.named("A")); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { return null; } }, new FailingElementVisitor() { @Override public Void visit(Message command) { assertEquals("More than one annotation is specified for this binding.", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSource(), "ElementsTest.java"); return null; } } ); } public void testBindWithMultipleTargetsAddsError() { checkModule( new AbstractModule() { protected void configure() { AnnotatedBindingBuilder abb = bind(String.class); abb.toInstance("A"); abb.toInstance("B"); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { return null; } }, new FailingElementVisitor() { @Override public Void visit(Message command) { assertEquals("Implementation is set more than once.", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSource(), "ElementsTest.java"); return null; } } ); } public void testBindWithMultipleScopesAddsError() { checkModule( new AbstractModule() { protected void configure() { ScopedBindingBuilder sbb = bind(List.class).to(ArrayList.class); sbb.in(Scopes.NO_SCOPE); sbb.asEagerSingleton(); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { return null; } }, new FailingElementVisitor() { @Override public Void visit(Message command) { assertEquals("Scope is set more than once.", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSource(), "ElementsTest.java"); return null; } } ); } public void testBindConstantWithMultipleAnnotationsAddsError() { checkModule( new AbstractModule() { protected void configure() { AnnotatedConstantBindingBuilder cbb = bindConstant(); cbb.annotatedWith(SampleAnnotation.class).to("A"); cbb.annotatedWith(Names.named("A")); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { return null; } }, new FailingElementVisitor() { @Override public Void visit(Message command) { assertEquals("More than one annotation is specified for this binding.", command.getMessage()); assertNull(command.getCause()); assertContains(command.getSource(), "ElementsTest.java"); return null; } } ); } public void testBindConstantWithMultipleTargetsAddsError() { checkModule( new AbstractModule() { protected void configure() { ConstantBindingBuilder cbb = bindConstant().annotatedWith(SampleAnnotation.class); cbb.to("A"); cbb.to("B"); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { return null; } }, new FailingElementVisitor() { @Override public Void visit(Message message) { assertEquals("Constant value is set more than once.", message.getMessage()); assertNull(message.getCause()); assertContains(message.getSource(), "ElementsTest.java"); return null; } } ); } public void testBindToConstructor() throws NoSuchMethodException, NoSuchFieldException { final Constructor aConstructor = A.class.getDeclaredConstructor(); final Constructor bConstructor = B.class.getDeclaredConstructor(Object.class); final Field field = B.class.getDeclaredField("stage"); checkModule( new AbstractModule() { protected void configure() { bind(A.class).toConstructor(aConstructor); bind(B.class).toConstructor(bConstructor, new TypeLiteral>() {}) .in(Singleton.class); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertEquals(new Key() {}, binding.getKey()); return binding.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(ConstructorBinding constructorBinding) { InjectionPoint injectionPoint = constructorBinding.getConstructor(); assertEquals(aConstructor, injectionPoint.getMember()); assertEquals(new TypeLiteral() {}, injectionPoint.getDeclaringType()); return null; } }); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertEquals(new Key() {}, binding.getKey()); binding.acceptScopingVisitor(new FailingBindingScopingVisitor() { @Override public Void visitScopeAnnotation(Class annotation) { assertEquals(Singleton.class, annotation); return null; } }); binding.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(ConstructorBinding constructorBinding) { assertEquals(bConstructor, constructorBinding.getConstructor().getMember()); assertEquals(Key.get(Integer.class), getOnlyElement(constructorBinding.getConstructor().getDependencies()).getKey()); assertEquals(field, getOnlyElement(constructorBinding.getInjectableMembers()).getMember()); assertEquals(2, constructorBinding.getDependencies().size()); /*if[AOP]*/ assertEquals(ImmutableMap.of(), constructorBinding.getMethodInterceptors()); /*end[AOP]*/ return null; } }); return null; } } ); } public void testBindToMalformedConstructor() throws NoSuchMethodException, NoSuchFieldException { final Constructor constructor = C.class.getDeclaredConstructor(Integer.class); checkModule( new AbstractModule() { protected void configure() { bind(C.class).toConstructor(constructor); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertEquals(Key.get(C.class), binding.getKey()); assertTrue(binding instanceof UntargettedBinding); return null; } }, new ExternalFailureVisitor() { @Override public Void visit(Message message) { assertContains(message.getMessage(), C.class.getName() + ".a has more than one annotation ", Named.class.getName(), SampleAnnotation.class.getName()); return null; } }, new ExternalFailureVisitor() { @Override public Void visit(Message message) { assertContains(message.getMessage(), C.class.getName() + ".() has more than one annotation ", Named.class.getName(), SampleAnnotation.class.getName()); return null; } } ); } // Business logic tests public void testModulesAreInstalledAtMostOnce() { final AtomicInteger aConfigureCount = new AtomicInteger(0); final Module a = new AbstractModule() { public void configure() { aConfigureCount.incrementAndGet(); } }; Elements.getElements(a, a); assertEquals(1, aConfigureCount.get()); aConfigureCount.set(0); Module b = new AbstractModule() { protected void configure() { install(a); install(a); } }; Elements.getElements(b); assertEquals(1, aConfigureCount.get()); } /** * Ensures the module performs the commands consistent with {@code visitors}. */ protected void checkModule(Module module, ElementVisitor... visitors) { List elements = Elements.getElements(module); assertEquals(elements.size(), visitors.length); checkElements(elements, visitors); } protected void checkElements(List elements, ElementVisitor... visitors) { for (int i = 0; i < visitors.length; i++) { ElementVisitor visitor = visitors[i]; Element element = elements.get(i); if (!(visitor instanceof ExternalFailureVisitor)) { assertContains(element.getSource().toString(), "ElementsTest.java"); } element.acceptVisitor(visitor); } } private static class ListProvider implements Provider { public List get() { return new ArrayList(); } } private static class TProvider implements Provider { public T get() { return null; } } /** * By extending this interface rather than FailingElementVisitor, the source of the error doesn't * need to contain the string {@code ElementsTest.java}. */ abstract class ExternalFailureVisitor extends FailingElementVisitor {} @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation public @interface SampleAnnotation { } public enum CoinSide { HEADS, TAILS } static class A { @Inject Stage stage; } static class B { @Inject Stage stage; B(T t) {} } static class C { @Inject @Named("foo") @SampleAnnotation String a; C(@Named("bar") @SampleAnnotation Integer b) {} } } guice-3.0/core/test/com/google/inject/spi/ToolStageInjectorTest.java0000644000175000017500000001200111460132764025454 0ustar drazzibdrazzibpackage com.google.inject.spi; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.TestCase; import com.google.inject.AbstractModule; import com.google.inject.Asserts; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Stage; import com.google.inject.spi.Toolable; public class ToolStageInjectorTest extends TestCase { @Override protected void setUp() throws Exception { Foo.s = null; Foo.sm = null; } public void testToolStageInjectorRestrictions() { Injector injector = Guice.createInjector(Stage.TOOL); try { injector.injectMembers(new Object()); fail("Non-SPI Injector methods must throw an exception in the TOOL stage."); } catch (UnsupportedOperationException expected) { } try { injector.getInstance(Injector.class); fail("Non-SPI Injector methods must throw an exception in the TOOL stage."); } catch (UnsupportedOperationException expected) { } try { injector.getInstance(Key.get(Injector.class)); fail("Non-SPI Injector methods must throw an exception in the TOOL stage."); } catch (UnsupportedOperationException expected) { } try { injector.getProvider(Injector.class); fail("Non-SPI Injector methods must throw an exception in the TOOL stage."); } catch (UnsupportedOperationException expected) { } try { injector.getProvider(Key.get(Injector.class)); fail("Non-SPI Injector methods must throw an exception in the TOOL stage."); } catch (UnsupportedOperationException expected) { } } public void testToolStageDoesntInjectInstances() { final Foo foo = new Foo(); Guice.createInjector(Stage.TOOL, new AbstractModule() { @Override protected void configure() { requestStaticInjection(Foo.class); requestInjection(foo); } }); assertNull(Foo.s); assertNull(Foo.sm); assertNull(foo.f); assertNull(foo.m); } public void testToolStageDoesntInjectProviders() { final Foo foo = new Foo(); Guice.createInjector(Stage.TOOL, new AbstractModule() { @Override protected void configure() { requestStaticInjection(Foo.class); bind(Object.class).toProvider(foo); } }); assertNull(Foo.s); assertNull(Foo.sm); assertNull(foo.f); assertNull(foo.m); } public void testToolStageWarnsOfMissingObjectGraph() { final Bar bar = new Bar(); try { Guice.createInjector(Stage.TOOL, new AbstractModule() { @Override protected void configure() { requestStaticInjection(Bar.class); requestInjection(bar); } }); fail("expected exception"); } catch(CreationException expected) { Asserts.assertContains(expected.toString(), "No implementation for java.util.Collection was bound.", "No implementation for java.util.Map was bound.", "No implementation for java.util.List was bound.", "No implementation for java.util.Set was bound."); } } public void testToolStageInjectsTooledMethods() { final Tooled tooled = new Tooled(); Guice.createInjector(Stage.TOOL, new AbstractModule() { @Override protected void configure() { requestStaticInjection(Tooled.class); bind(Object.class).toProvider(tooled); } }); assertNull(Tooled.s); assertNotNull(Tooled.sm); assertNull(tooled.f); assertNotNull(tooled.m); } @SuppressWarnings("unchecked") private static class Bar { @SuppressWarnings("unused") @Inject private static List list; @SuppressWarnings("unused") @Inject private Set set; @SuppressWarnings("unused") @Inject void method(Collection c) {} @SuppressWarnings("unused") @Inject static void staticMethod(Map map) {} } private static class Foo implements Provider { @Inject private static S s; @Inject private F f; private M m; @SuppressWarnings("unused") @Inject void method(M m) { this.m = m; } private static SM sm; @SuppressWarnings("unused") @Inject static void staticMethod(SM sm) { Tooled.sm = sm; } public Object get() { return null; } } private static class Tooled implements Provider { @Inject private static S s; @Inject private F f; private M m; @Toolable @SuppressWarnings("unused") @Inject void method(M m) { this.m = m; } private static SM sm; @Toolable @SuppressWarnings("unused") @Inject static void staticMethod(SM sm) { Tooled.sm = sm; } public Object get() { return null; } } private static class S {} private static class F {} private static class M {} private static class SM {} } guice-3.0/core/test/com/google/inject/spi/FailingTargetVisitor.java0000644000175000017500000000161311460132764025324 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; import junit.framework.AssertionFailedError; public class FailingTargetVisitor extends DefaultBindingTargetVisitor { @Override protected Void visitOther(Binding binding) { throw new AssertionFailedError(); } } guice-3.0/core/test/com/google/inject/spi/FailingElementVisitor.java0000644000175000017500000000151211460132764025465 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import junit.framework.AssertionFailedError; class FailingElementVisitor extends DefaultElementVisitor { @Override protected Void visitOther(Element element) { throw new AssertionFailedError(); } } guice-3.0/core/test/com/google/inject/spi/ProviderMethodsTest.java0000644000175000017500000002750411461133116025202 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.AbstractModule; import static com.google.inject.Asserts.assertContains; import com.google.inject.Binder; import com.google.inject.BindingAnnotation; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.Provides; import com.google.inject.Singleton; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.ProviderMethod; import com.google.inject.internal.ProviderMethodsModule; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.google.inject.util.Types; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Logger; import junit.framework.TestCase; /** * @author crazybob@google.com (Bob Lee) */ public class ProviderMethodsTest extends TestCase implements Module { @SuppressWarnings("unchecked") public void testProviderMethods() { Injector injector = Guice.createInjector(this); Bob bob = injector.getInstance(Bob.class); assertEquals("A Bob", bob.getName()); Bob clone = injector.getInstance(Bob.class); assertEquals("A Bob", clone.getName()); assertNotSame(bob, clone); assertSame(bob.getDaughter(), clone.getDaughter()); Key soleBobKey = Key.get(Bob.class, Sole.class); assertSame( injector.getInstance(soleBobKey), injector.getInstance(soleBobKey) ); } public void configure(Binder binder) {} interface Bob { String getName(); Dagny getDaughter(); } interface Dagny { int getAge(); } @Provides Bob provideBob(final Dagny dagny) { return new Bob() { public String getName() { return "A Bob"; } public Dagny getDaughter() { return dagny; } }; } @Provides @Singleton @Sole Bob provideSoleBob(final Dagny dagny) { return new Bob() { public String getName() { return "Only Bob"; } public Dagny getDaughter() { return dagny; } }; } @Provides @Singleton Dagny provideDagny() { return new Dagny() { public int getAge() { return 1; } }; } @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation @interface Sole {} // We'll have to make getProvider() support circular dependencies before this // will work. // // public void testCircularDependency() { // Injector injector = Guice.createInjector(new Module() { // public void configure(Binder binder) { // binder.install(ProviderMethods.from(ProviderMethodsTest.this)); // } // }); // // Foo foo = injector.getInstance(Foo.class); // assertEquals(5, foo.getI()); // assertEquals(10, foo.getBar().getI()); // assertEquals(5, foo.getBar().getFoo().getI()); // } // // interface Foo { // Bar getBar(); // int getI(); // } // // interface Bar { // Foo getFoo(); // int getI(); // } // // @Provides Foo newFoo(final Bar bar) { // return new Foo() { // // public Bar getBar() { // return bar; // } // // public int getI() { // return 5; // } // }; // } // // @Provides Bar newBar(final Foo foo) { // return new Bar() { // // public Foo getFoo() { // return foo; // } // // public int getI() { // return 10; // } // }; // } public void testMultipleBindingAnnotations() { try { Guice.createInjector(new AbstractModule() { protected void configure() {} @Provides @Named("A") @Blue public String provideString() { return "a"; } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "more than one annotation annotated with @BindingAnnotation:", "Named", "Blue", "at " + getClass().getName(), ".provideString(ProviderMethodsTest.java:"); } } @Retention(RUNTIME) @BindingAnnotation @interface Blue {} public void testGenericProviderMethods() { Injector injector = Guice.createInjector( new ProvideTs("A", "B") {}, new ProvideTs(1, 2) {}); assertEquals("A", injector.getInstance(Key.get(String.class, Names.named("First")))); assertEquals("B", injector.getInstance(Key.get(String.class, Names.named("Second")))); assertEquals(ImmutableSet.of("A", "B"), injector.getInstance(Key.get(Types.setOf(String.class)))); assertEquals(1, injector.getInstance(Key.get(Integer.class, Names.named("First"))).intValue()); assertEquals(2, injector.getInstance(Key.get(Integer.class, Names.named("Second"))).intValue()); assertEquals(ImmutableSet.of(1, 2), injector.getInstance(Key.get(Types.setOf(Integer.class)))); } abstract class ProvideTs extends AbstractModule { final T first; final T second; protected ProvideTs(T first, T second) { this.first = first; this.second = second; } protected void configure() {} @Named("First") @Provides T provideFirst() { return first; } @Named("Second") @Provides T provideSecond() { return second; } @Provides Set provideBoth(@Named("First") T first, @Named("Second") T second) { return ImmutableSet.of(first, second); } } public void testAutomaticProviderMethods() { Injector injector = Guice.createInjector((Module) new AbstractModule() { protected void configure() { } private int next = 1; @Provides @Named("count") public Integer provideCount() { return next++; } }); assertEquals(1, injector.getInstance(Key.get(Integer.class, Names.named("count"))).intValue()); assertEquals(2, injector.getInstance(Key.get(Integer.class, Names.named("count"))).intValue()); assertEquals(3, injector.getInstance(Key.get(Integer.class, Names.named("count"))).intValue()); } /** * If the user installs provider methods for the module manually, that shouldn't cause a double * binding of the provider methods' types. */ public void testAutomaticProviderMethodsDoNotCauseDoubleBinding() { Module installsSelf = new AbstractModule() { protected void configure() { install(this); bind(Integer.class).toInstance(5); } @Provides public String provideString(Integer count) { return "A" + count; } }; Injector injector = Guice.createInjector(installsSelf); assertEquals("A5", injector.getInstance(String.class)); } public void testWildcardProviderMethods() { final List strings = ImmutableList.of("A", "B", "C"); final List numbers = ImmutableList.of(1, 2, 3); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { @SuppressWarnings("unchecked") Key> listOfSupertypesOfInteger = (Key>) Key.get(Types.listOf(Types.supertypeOf(Integer.class))); bind(listOfSupertypesOfInteger).toInstance(numbers); } @Provides public List provideCharSequences() { return strings; } @Provides public Class provideType() { return Float.class; } }); assertSame(strings, injector.getInstance(HasWildcardInjection.class).charSequences); assertSame(numbers, injector.getInstance(HasWildcardInjection.class).numbers); assertSame(Float.class, injector.getInstance(HasWildcardInjection.class).type); } static class HasWildcardInjection { @Inject List charSequences; @Inject List numbers; @Inject Class type; } public void testProviderMethodDependenciesAreExposed() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Integer.class).toInstance(50); bindConstant().annotatedWith(Names.named("units")).to("Kg"); } @Provides @Named("weight") String provideWeight(Integer count, @Named("units") String units) { return count + units; } }); ProviderInstanceBinding binding = (ProviderInstanceBinding) injector.getBinding( Key.get(String.class, Names.named("weight"))); assertEquals(ImmutableSet.>of(Dependency.get(Key.get(Integer.class)), Dependency.get(Key.get(String.class, Names.named("units")))), binding.getDependencies()); } public void testNonModuleProviderMethods() { final Object methodsObject = new Object() { @Provides @Named("foo") String provideFoo() { return "foo-value"; } }; Module module = new AbstractModule() { @Override protected void configure() { install(ProviderMethodsModule.forObject(methodsObject)); } }; Injector injector = Guice.createInjector(module); Key key = Key.get(String.class, Names.named("foo")); assertEquals("foo-value", injector.getInstance(key)); // Test the provider method object itself. This makes sure getInstance works, since GIN uses it List elements = Elements.getElements(module); assertEquals(1, elements.size()); Element element = elements.get(0); assertTrue(element + " instanceof ProviderInstanceBinding", element instanceof ProviderInstanceBinding); ProviderInstanceBinding binding = (ProviderInstanceBinding) element; Provider provider = binding.getProviderInstance(); assertEquals(ProviderMethod.class, provider.getClass()); assertEquals(methodsObject, ((ProviderMethod) provider).getInstance()); } public void testVoidProviderMethods() { try { Guice.createInjector(new AbstractModule() { protected void configure() {} @Provides void provideFoo() {} }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Provider methods must return a value. Do not return void.", getClass().getName(), ".provideFoo(ProviderMethodsTest.java:"); } } public void testInjectsJustOneLogger() { AtomicReference loggerRef = new AtomicReference(); Injector injector = Guice.createInjector(new FooModule(loggerRef)); assertNull(loggerRef.get()); injector.getInstance(Integer.class); Logger lastLogger = loggerRef.getAndSet(null); assertNotNull(lastLogger); injector.getInstance(Integer.class); assertSame(lastLogger, loggerRef.get()); assertEquals(FooModule.class.getName() + ".foo", lastLogger.getName()); } private static class FooModule extends AbstractModule { private final AtomicReference loggerRef; public FooModule(AtomicReference loggerRef) { this.loggerRef = loggerRef; } @Override protected void configure() {} @SuppressWarnings("unused") @Provides Integer foo(Logger logger) { loggerRef.set(logger); return 42; } } }guice-3.0/core/test/com/google/inject/spi/SpiBindingsTest.java0000644000175000017500000003773711460132764024315 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.AbstractModule; import static com.google.inject.Asserts.assertContains; import com.google.inject.Binding; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.Scopes; import com.google.inject.Singleton; import com.google.inject.Stage; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import com.google.inject.name.Names; import java.lang.reflect.Constructor; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; import junit.framework.AssertionFailedError; import junit.framework.TestCase; /** * @author jessewilson@google.com (Jesse Wilson) */ public class SpiBindingsTest extends TestCase { public void testBindConstant() { checkInjector( new AbstractModule() { protected void configure() { bindConstant().annotatedWith(Names.named("one")).to(1); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertTrue(binding instanceof InstanceBinding); assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey()); return null; } } ); } public void testToInstanceBinding() { checkInjector( new AbstractModule() { protected void configure() { bind(String.class).toInstance("A"); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertTrue(binding instanceof InstanceBinding); assertContains(binding.getSource().toString(), "SpiBindingsTest.java"); assertEquals(Key.get(String.class), binding.getKey()); binding.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(InstanceBinding binding) { assertEquals("A", binding.getInstance()); return null; } }); binding.acceptScopingVisitor(new FailingBindingScopingVisitor() { public Void visitEagerSingleton() { return null; } }); return null; } } ); } public void testToProviderBinding() { final Provider stringProvider = new StringProvider(); checkInjector( new AbstractModule() { protected void configure() { bind(String.class).toProvider(stringProvider); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertTrue(binding instanceof ProviderInstanceBinding); assertContains(binding.getSource().toString(), "SpiBindingsTest.java"); assertEquals(Key.get(String.class), binding.getKey()); binding.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit( ProviderInstanceBinding binding) { assertSame(stringProvider, binding.getProviderInstance()); return null; } }); return null; } } ); } public void testToProviderKeyBinding() { checkInjector( new AbstractModule() { protected void configure() { bind(String.class).toProvider(StringProvider.class); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertTrue(binding instanceof ProviderKeyBinding); assertContains(binding.getSource().toString(), "SpiBindingsTest.java"); assertEquals(Key.get(String.class), binding.getKey()); binding.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(ProviderKeyBinding binding) { assertEquals(Key.get(StringProvider.class), binding.getProviderKey()); return null; } }); return null; } } ); } public void testToKeyBinding() { final Key aKey = Key.get(String.class, Names.named("a")); final Key bKey = Key.get(String.class, Names.named("b")); checkInjector( new AbstractModule() { protected void configure() { bind(aKey).to(bKey); bind(bKey).toInstance("B"); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertTrue(binding instanceof LinkedKeyBinding); assertContains(binding.getSource().toString(), "SpiBindingsTest.java"); assertEquals(aKey, binding.getKey()); binding.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(LinkedKeyBinding binding) { assertEquals(bKey, binding.getLinkedKey()); return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertEquals(bKey, binding.getKey()); return null; } } ); } public void testToConstructorBinding() { checkInjector( new AbstractModule() { protected void configure() { bind(D.class); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertTrue(binding instanceof ConstructorBinding); assertContains(binding.getSource().toString(), "SpiBindingsTest.java"); assertEquals(Key.get(D.class), binding.getKey()); binding.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(ConstructorBinding binding) { Constructor expected = D.class.getDeclaredConstructors()[0]; assertEquals(expected, binding.getConstructor().getMember()); assertEquals(ImmutableSet.of(), binding.getInjectableMembers()); return null; } }); return null; } } ); } public void testConstantBinding() { checkInjector( new AbstractModule() { protected void configure() { bindConstant().annotatedWith(Names.named("one")).to(1); } }, new FailingElementVisitor() { @Override public Void visit(Binding binding) { assertTrue(binding instanceof InstanceBinding); assertContains(binding.getSource().toString(), "SpiBindingsTest.java"); assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey()); binding.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit(InstanceBinding binding) { assertEquals(1, binding.getInstance()); return null; } }); return null; } } ); } public void testConvertedConstantBinding() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bindConstant().annotatedWith(Names.named("one")).to("1"); } }); Binding binding = injector.getBinding(Key.get(Integer.class, Names.named("one"))); assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey()); assertContains(binding.getSource().toString(), "SpiBindingsTest.java"); assertTrue(binding instanceof ConvertedConstantBinding); binding.acceptTargetVisitor(new FailingTargetVisitor() { @Override public Void visit( ConvertedConstantBinding binding) { assertEquals((Integer) 1, binding.getValue()); assertEquals(Key.get(String.class, Names.named("one")), binding.getSourceKey()); return null; } }); } public void testProviderBinding() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toInstance("A"); } }); Key> providerOfStringKey = new Key>() {}; Binding> binding = injector.getBinding(providerOfStringKey); assertEquals(providerOfStringKey, binding.getKey()); assertContains(binding.getSource().toString(), "SpiBindingsTest.java"); assertTrue(binding instanceof ProviderBinding); binding.acceptTargetVisitor(new FailingTargetVisitor>() { @Override public Void visit( ProviderBinding> binding) { assertEquals(Key.get(String.class), binding.getProvidedKey()); return null; } }); } public void testScopes() { checkInjector( new AbstractModule() { protected void configure() { bind(String.class).annotatedWith(Names.named("a")) .toProvider(StringProvider.class).in(Singleton.class); bind(String.class).annotatedWith(Names.named("b")) .toProvider(StringProvider.class).in(Scopes.SINGLETON); bind(String.class).annotatedWith(Names.named("c")) .toProvider(StringProvider.class).asEagerSingleton(); bind(String.class).annotatedWith(Names.named("d")) .toProvider(StringProvider.class); } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(String.class, Names.named("a")), command.getKey()); command.acceptScopingVisitor(new FailingBindingScopingVisitor() { @Override public Void visitScope(Scope scope) { // even though we bound with an annotation, the injector always uses instances assertSame(Scopes.SINGLETON, scope); return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(String.class, Names.named("b")), command.getKey()); command.acceptScopingVisitor(new FailingBindingScopingVisitor() { @Override public Void visitScope(Scope scope) { assertSame(Scopes.SINGLETON, scope); return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(String.class, Names.named("c")), command.getKey()); command.acceptScopingVisitor(new FailingBindingScopingVisitor() { @Override public Void visitEagerSingleton() { return null; } }); return null; } }, new FailingElementVisitor() { @Override public Void visit(Binding command) { assertEquals(Key.get(String.class, Names.named("d")), command.getKey()); command.acceptScopingVisitor(new FailingBindingScopingVisitor() { @Override public Void visitNoScoping() { return null; } }); return null; } } ); } public void testExtensionSpi() { final AtomicBoolean visiting = new AtomicBoolean(false); final Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(String.class).toProvider(new ProviderWithExtensionVisitor() { public V acceptExtensionVisitor(BindingTargetVisitor visitor, ProviderInstanceBinding binding) { assertSame(this, binding.getProviderInstance()); // We can't always check for FailingSpiTargetVisitor, // because constructing the injector visits here, and we need // to process the binding as normal if(visiting.get()) { assertTrue("visitor: " + visitor, visitor instanceof FailingSpiTargetVisitor); return (V)"visited"; } else { return visitor.visit(binding); } } public String get() { return "FooBar"; } }); } }); visiting.set(true); // Check for Provider binding -- that is still a ProviderBinding. Key> providerOfStringKey = new Key>() {}; Binding> providerBinding = injector.getBinding(providerOfStringKey); assertEquals(providerOfStringKey, providerBinding.getKey()); assertContains(providerBinding.getSource().toString(), "SpiBindingsTest.java"); assertTrue("binding: " + providerBinding, providerBinding instanceof ProviderBinding); providerBinding.acceptTargetVisitor(new FailingTargetVisitor>() { @Override public Void visit(ProviderBinding> binding) { assertEquals(Key.get(String.class), binding.getProvidedKey()); return null; } }); // Check for String binding -- that one is ProviderInstanceBinding, and gets hooked Binding binding = injector.getBinding(String.class); assertEquals(Key.get(String.class), binding.getKey()); assertContains(binding.getSource().toString(), "SpiBindingsTest.java"); assertTrue(binding instanceof ProviderInstanceBinding); assertEquals("visited", binding.acceptTargetVisitor(new FailingSpiTargetVisitor())); } private static class FailingSpiTargetVisitor extends DefaultBindingTargetVisitor { @Override protected String visitOther(Binding binding) { throw new AssertionFailedError(); } } public void checkInjector(Module module, ElementVisitor... visitors) { Injector injector = Guice.createInjector(module); List> bindings = Lists.newArrayList(injector.getBindings().values()); for (Iterator> i = bindings.iterator(); i.hasNext(); ) { if (BUILT_IN_BINDINGS.contains(i.next().getKey())) { i.remove(); } } Collections.sort(bindings, orderByKey); assertEquals(bindings.size(), visitors.length); for (int i = 0; i < visitors.length; i++) { ElementVisitor visitor = visitors[i]; Binding binding = bindings.get(i); binding.acceptVisitor(visitor); } } private final ImmutableSet> BUILT_IN_BINDINGS = ImmutableSet.of( Key.get(Injector.class), Key.get(Stage.class), Key.get(Logger.class)); private final Comparator> orderByKey = new Comparator>() { public int compare(Binding a, Binding b) { return a.getKey().toString().compareTo(b.getKey().toString()); } }; private static class StringProvider implements Provider { public String get() { return "A"; } } private static class C { } private static class D extends C { @Inject public D(Injector unused) { } } } guice-3.0/core/test/com/google/inject/CircularDependencyTest.java0000644000175000017500000001252711530444452025040 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import junit.framework.TestCase; import static com.google.inject.Asserts.assertContains; /** * @author crazybob@google.com (Bob Lee) */ public class CircularDependencyTest extends TestCase { @Override protected void setUp() throws Exception { super.setUp(); Chicken.nextInstanceId = 0; Egg.nextInstanceId = 0; } public void testCircularlyDependentConstructors() throws CreationException { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(A.class).to(AImpl.class); bind(B.class).to(BImpl.class); } }); A a = injector.getInstance(A.class); assertNotNull(a.getB().getA()); } interface A { B getB(); } @Singleton static class AImpl implements A { final B b; @Inject public AImpl(B b) { this.b = b; } public B getB() { return b; } } interface B { A getA(); } static class BImpl implements B { final A a; @Inject public BImpl(A a) { this.a = a; } public A getA() { return a; } } public void testUnresolvableCircularDependency() { try { Guice.createInjector().getInstance(C.class); fail(); } catch (ProvisionException expected) { assertContains(expected.getMessage(), "Tried proxying " + C.class.getName() + " to support a circular dependency, ", "but it is not an interface."); } } static class C { @Inject C(D d) {} } static class D { @Inject D(C c) {} } /** * As reported by issue 349, we give a lousy trace when a class is circularly * dependent on itself in multiple ways. */ public void testCircularlyDependentMultipleWays() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { binder.bind(A.class).to(E.class); binder.bind(B.class).to(E.class); } }); injector.getInstance(A.class); } public void testDisablingCircularProxies() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { binder().disableCircularProxies(); binder.bind(A.class).to(E.class); binder.bind(B.class).to(E.class); } }); try { injector.getInstance(A.class); fail("expected exception"); } catch(ProvisionException expected) { assertContains(expected.getMessage(), "Tried proxying " + A.class.getName() + " to support a circular dependency, but circular proxies are disabled", "Tried proxying " + B.class.getName() + " to support a circular dependency, but circular proxies are disabled"); } } @Singleton static class E implements A, B { @Inject public E(A a, B b) {} public B getB() { return this; } public A getA() { return this; } } static class Chicken { static int nextInstanceId; final int instanceId = nextInstanceId++; @Inject Egg source; } static class Egg { static int nextInstanceId; final int instanceId = nextInstanceId++; @Inject Chicken source; } public void testCircularlyDependentSingletonsWithProviders() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(Chicken.class).in(Singleton.class); } @Provides @Singleton Egg provideEgg(Chicken chicken) { Egg egg = new Egg(); egg.source = chicken; return egg; } }); try { injector.getInstance(Egg.class); fail(); } catch (ProvisionException e) { assertContains(e.getMessage(), "Provider was reentrant while creating a singleton", " at " + CircularDependencyTest.class.getName(), "provideEgg(", " while locating " + Egg.class.getName()); } } public void testCircularDependencyProxyDelegateNeverInitialized() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(F.class).to(RealF.class); bind(G.class).to(RealG.class); } }); F f = injector.getInstance(F.class); assertEquals("F", f.g().f().toString()); assertEquals("G", f.g().f().g().toString()); } public interface F { G g(); } @Singleton public static class RealF implements F { private final G g; @Inject RealF(G g) { this.g = g; } public G g() { return g; } @Override public String toString() { return "F"; } } public interface G { F f(); } @Singleton public static class RealG implements G { private final F f; @Inject RealG(F f) { this.f = f; } public F f() { return f; } @Override public String toString() { return "G"; } } } guice-3.0/core/test/com/google/inject/AllTests.java0000644000175000017500000001505211460132772022165 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.internal.util.FinalizableReferenceQueueTest; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Jsr166HashMapTest; import com.google.inject.internal.util.LineNumbersTest; import com.google.inject.internal.util.MapMakerTestSuite; import com.google.inject.internal.MoreTypesTest; import com.google.inject.internal.UniqueAnnotationsTest; import com.google.inject.matcher.MatcherTest; import com.google.inject.name.NamedEquivalanceTest; import com.google.inject.name.NamesTest; import com.google.inject.spi.BindingTargetVisitorTest; import com.google.inject.spi.ElementApplyToTest; import com.google.inject.spi.ElementsTest; import com.google.inject.spi.HasDependenciesTest; import com.google.inject.spi.InjectionPointTest; import com.google.inject.spi.InjectorSpiTest; import com.google.inject.spi.ModuleRewriterTest; import com.google.inject.spi.ProviderMethodsTest; import com.google.inject.spi.SpiBindingsTest; import com.google.inject.spi.ToolStageInjectorTest; import com.google.inject.util.NoopOverrideTest; import com.google.inject.util.ProvidersTest; import com.google.inject.util.TypesTest; import com.googlecode.guice.Jsr330Test; import com.googlecode.guice.GuiceTck; import java.util.Enumeration; import java.util.Set; import junit.framework.Test; import junit.framework.TestSuite; /** * @author crazybob@google.com (Bob Lee) */ public class AllTests { private static final Set SUPPRESSED_TEST_NAMES = ImmutableSet.of( "testUnscopedProviderWorksOutsideOfRequestedScope(" + ScopesTest.class.getName() + ")", "testCannotConvertUnannotatedBindings(" + TypeConversionTest.class.getName() + ")" ); public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(GuiceTck.suite()); suite.addTestSuite(BinderTest.class); suite.addTest(BinderTestSuite.suite()); suite.addTestSuite(BindingAnnotationTest.class); suite.addTestSuite(BindingOrderTest.class); suite.addTestSuite(BindingTest.class); suite.addTestSuite(BoundInstanceInjectionTest.class); suite.addTestSuite(BoundProviderTest.class); suite.addTestSuite(CircularDependencyTest.class); suite.addTestSuite(DuplicateBindingsTest.class); // ErrorHandlingTest.class is not a testcase suite.addTestSuite(EagerSingletonTest.class); suite.addTestSuite(GenericInjectionTest.class); suite.addTestSuite(ImplicitBindingTest.class); suite.addTestSuite(TypeListenerTest.class); suite.addTestSuite(InjectorTest.class); suite.addTestSuite(JitBindingsTest.class); // IntegrationTest is AOP-only suite.addTestSuite(KeyTest.class); suite.addTestSuite(LoggerInjectionTest.class); // MethodInterceptionTest is AOP-only suite.addTestSuite(MembersInjectorTest.class); suite.addTestSuite(ModulesTest.class); suite.addTestSuite(ModuleTest.class); suite.addTestSuite(NullableInjectionPointTest.class); suite.addTestSuite(OptionalBindingTest.class); suite.addTestSuite(OverrideModuleTest.class); suite.addTestSuite(ParentInjectorTest.class); suite.addTestSuite(PrivateModuleTest.class); suite.addTestSuite(ProviderInjectionTest.class); suite.addTestSuite(ProvisionExceptionTest.class); // ProxyFactoryTest is AOP-only suite.addTestSuite(ReflectionTest.class); suite.addTestSuite(RequestInjectionTest.class); suite.addTestSuite(ScopesTest.class); suite.addTestSuite(SerializationTest.class); suite.addTestSuite(SuperclassTest.class); suite.addTestSuite(TypeConversionTest.class); suite.addTestSuite(TypeLiteralInjectionTest.class); suite.addTestSuite(TypeLiteralTest.class); suite.addTestSuite(TypeLiteralTypeResolutionTest.class); // internal suite.addTestSuite(FinalizableReferenceQueueTest.class); suite.addTestSuite(Jsr166HashMapTest.class); suite.addTestSuite(LineNumbersTest.class); suite.addTest(MapMakerTestSuite.suite()); suite.addTestSuite(MoreTypesTest.class); suite.addTestSuite(UniqueAnnotationsTest.class); // matcher suite.addTestSuite(MatcherTest.class); // names suite.addTestSuite(NamesTest.class); suite.addTestSuite(NamedEquivalanceTest.class); // spi suite.addTestSuite(BindingTargetVisitorTest.class); suite.addTestSuite(ElementsTest.class); suite.addTestSuite(ElementApplyToTest.class); suite.addTestSuite(HasDependenciesTest.class); suite.addTestSuite(InjectionPointTest.class); suite.addTestSuite(InjectorSpiTest.class); suite.addTestSuite(ModuleRewriterTest.class); suite.addTestSuite(ProviderMethodsTest.class); suite.addTestSuite(SpiBindingsTest.class); suite.addTestSuite(ToolStageInjectorTest.class); // tools // suite.addTestSuite(JmxTest.class); not a testcase // util suite.addTestSuite(NoopOverrideTest.class); suite.addTestSuite(ProvidersTest.class); suite.addTestSuite(TypesTest.class); /*if[AOP]*/ suite.addTestSuite(com.google.inject.internal.ProxyFactoryTest.class); suite.addTestSuite(IntegrationTest.class); suite.addTestSuite(MethodInterceptionTest.class); suite.addTestSuite(com.googlecode.guice.BytecodeGenTest.class); /*end[AOP]*/ // googlecode.guice suite.addTest(com.googlecode.guice.StrictContainerTestSuite.suite()); suite.addTestSuite(com.googlecode.guice.OSGiContainerTest.class); suite.addTestSuite(Jsr330Test.class); return removeSuppressedTests(suite, SUPPRESSED_TEST_NAMES); } public static TestSuite removeSuppressedTests(TestSuite suite, Set suppressedTestNames) { TestSuite result = new TestSuite(suite.getName()); for(Enumeration e = suite.tests(); e.hasMoreElements(); ) { Test test = (Test) e.nextElement(); if (suppressedTestNames.contains(test.toString())) { continue; } if (test instanceof TestSuite) { result.addTest(removeSuppressedTests((TestSuite) test, suppressedTestNames)); } else { result.addTest(test); } } return result; } } guice-3.0/core/test/com/google/inject/TypeLiteralTypeResolutionTest.java0000644000175000017500000003232111460132772026454 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static com.google.inject.Asserts.assertEqualsBothWays; import static com.google.inject.Asserts.assertNotSerializable; import com.google.inject.internal.util.ImmutableList; import com.google.inject.util.Types; import static com.google.inject.util.Types.arrayOf; import static com.google.inject.util.Types.listOf; import static com.google.inject.util.Types.newParameterizedType; import static com.google.inject.util.Types.newParameterizedTypeWithOwner; import static com.google.inject.util.Types.setOf; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.AbstractCollection; import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.TestCase; /** * This test checks that TypeLiteral can perform type resolution on its members. * * @author jessewilson@google.com (Jesse Wilson) */ public class TypeLiteralTypeResolutionTest extends TestCase { Type arrayListOfString = newParameterizedType(ArrayList.class, String.class); Type hasGenericFieldsOfShort = newParameterizedTypeWithOwner( getClass(), HasGenericFields.class, Short.class); Type hasGenericConstructorOfShort = newParameterizedTypeWithOwner( getClass(), GenericConstructor.class, Short.class); Type throwerOfNpe = newParameterizedTypeWithOwner( getClass(), Thrower.class, NullPointerException.class); Type hasArrayOfShort = newParameterizedTypeWithOwner(getClass(), HasArray.class, Short.class); Type hasRelatedOfString = newParameterizedTypeWithOwner( getClass(), HasRelated.class, String.class, String.class); Type mapK = Map.class.getTypeParameters()[0]; Type hashMapK = HashMap.class.getTypeParameters()[0]; Type setEntryKV; Type entryStringInteger = setOf(newParameterizedTypeWithOwner( Map.class, Map.Entry.class, String.class, Integer.class)); Field list; Field instance; Constructor newHasGenericConstructor; Constructor newThrower; Constructor newString; Method stringIndexOf; Method comparableCompareTo; Method getArray; Method getSetOfArray; Method echo; Method throwS; @Override protected void setUp() throws Exception { super.setUp(); list = HasGenericFields.class.getField("list"); instance = HasGenericFields.class.getField("instance"); newHasGenericConstructor = GenericConstructor.class.getConstructor(Object.class, Object.class); newThrower = Thrower.class.getConstructor(); stringIndexOf = String.class.getMethod("indexOf", String.class); newString = String.class.getConstructor(String.class); comparableCompareTo = Comparable.class.getMethod("compareTo", Object.class); getArray = HasArray.class.getMethod("getArray"); getSetOfArray = HasArray.class.getMethod("getSetOfArray"); echo = HasRelated.class.getMethod("echo", Object.class); throwS = Thrower.class.getMethod("throwS"); setEntryKV = HashMap.class.getMethod("entrySet").getGenericReturnType(); } public void testDirectInheritance() throws NoSuchMethodException { TypeLiteral resolver = TypeLiteral.get(arrayListOfString); assertEquals(listOf(String.class), resolver.getReturnType(List.class.getMethod("subList", int.class, int.class)).getType()); assertEquals(ImmutableList.>of(TypeLiteral.get(String.class)), resolver.getParameterTypes(Collection.class.getMethod("add", Object.class))); } public void testGenericSupertype() { TypeLiteral resolver = TypeLiteral.get(arrayListOfString); assertEquals(newParameterizedType(Collection.class, String.class), resolver.getSupertype(Collection.class).getType()); assertEquals(newParameterizedType(Iterable.class, String.class), resolver.getSupertype(Iterable.class).getType()); assertEquals(newParameterizedType(AbstractList.class, String.class), resolver.getSupertype(AbstractList.class).getType()); assertEquals(Object.class, resolver.getSupertype(Object.class).getType()); } public void testRecursiveTypeVariable() { TypeLiteral resolver = TypeLiteral.get(MyInteger.class); assertEquals(MyInteger.class, resolver.getParameterTypes(comparableCompareTo).get(0).getType()); } interface MyComparable> extends Comparable {} static class MyInteger implements MyComparable { int value; public int compareTo(MyInteger o) { return value - o.value; } } public void testFields() { TypeLiteral resolver = TypeLiteral.get(hasGenericFieldsOfShort); assertEquals(listOf(Short.class), resolver.getFieldType(list).getType()); assertEquals(Short.class, resolver.getFieldType(instance).getType()); } static class HasGenericFields { public List list; public T instance; } public void testGenericConstructor() throws NoSuchMethodException { TypeLiteral resolver = TypeLiteral.get(hasGenericConstructorOfShort); assertEquals(Short.class, resolver.getParameterTypes(newHasGenericConstructor).get(0).getType()); } static class GenericConstructor { @SuppressWarnings("UnusedDeclaration") public GenericConstructor(S s, T t) {} } public void testThrowsExceptions() { TypeLiteral type = TypeLiteral.get(throwerOfNpe); assertEquals(NullPointerException.class, type.getExceptionTypes(newThrower).get(0).getType()); assertEquals(NullPointerException.class, type.getExceptionTypes(throwS).get(0).getType()); } static class Thrower { public Thrower() throws S {} public void throwS() throws S {} } public void testArrays() { TypeLiteral resolver = TypeLiteral.get(hasArrayOfShort); assertEquals(arrayOf(Short.class), resolver.getReturnType(getArray).getType()); assertEquals(setOf(arrayOf(Short.class)), resolver.getReturnType(getSetOfArray).getType()); } static interface HasArray { T[] getArray(); Set getSetOfArray(); } public void testRelatedTypeVariables() { TypeLiteral resolver = TypeLiteral.get(hasRelatedOfString); assertEquals(String.class, resolver.getParameterTypes(echo).get(0).getType()); assertEquals(String.class, resolver.getReturnType(echo).getType()); } interface HasRelated { T echo(R r); } /** Ensure the cache doesn't cache too much */ public void testCachingAndReindexing() throws NoSuchMethodException { TypeLiteral resolver = TypeLiteral.get( newParameterizedTypeWithOwner(getClass(), HasLists.class, String.class, Short.class)); assertEquals(listOf(String.class), resolver.getReturnType(HasLists.class.getMethod("listS")).getType()); assertEquals(listOf(Short.class), resolver.getReturnType(HasLists.class.getMethod("listT")).getType()); } interface HasLists { List listS(); List listT(); List> listEntries(); } public void testUnsupportedQueries() throws NoSuchMethodException { TypeLiteral resolver = TypeLiteral.get(arrayListOfString); try { resolver.getExceptionTypes(stringIndexOf); fail(); } catch (IllegalArgumentException e) { assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a " + "supertype of java.util.ArrayList", e.getMessage()); } try { resolver.getParameterTypes(stringIndexOf); fail(); } catch (Exception e) { assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a " + "supertype of java.util.ArrayList", e.getMessage()); } try { resolver.getReturnType(stringIndexOf); fail(); } catch (Exception e) { assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a " + "supertype of java.util.ArrayList", e.getMessage()); } try { resolver.getSupertype(String.class); fail(); } catch (Exception e) { assertEquals("class java.lang.String is not a supertype of " + "java.util.ArrayList", e.getMessage()); } try { resolver.getExceptionTypes(newString); fail(); } catch (Exception e) { assertEquals("public java.lang.String(java.lang.String) does not construct " + "a supertype of java.util.ArrayList", e.getMessage()); } try { resolver.getParameterTypes(newString); fail(); } catch (Exception e) { assertEquals("public java.lang.String(java.lang.String) does not construct " + "a supertype of java.util.ArrayList", e.getMessage()); } } public void testResolve() { TypeLiteral typeResolver = TypeLiteral.get(StringIntegerMap.class); assertEquals(String.class, typeResolver.resolveType(mapK)); typeResolver = new TypeLiteral>() {}; assertEquals(String.class, typeResolver.resolveType(mapK)); assertEquals(Types.mapOf(String.class, Integer.class), typeResolver.getSupertype(Map.class).getType()); typeResolver = new TypeLiteral>() {}; assertEquals(String.class, typeResolver.resolveType(mapK)); typeResolver = new TypeLiteral>() {}; assertEquals(String.class, typeResolver.resolveType(mapK)); typeResolver = TypeLiteral.get(StringIntegerHashMap.class); assertEquals(String.class, typeResolver.resolveType(mapK)); assertEquals(String.class, typeResolver.resolveType(hashMapK)); assertEquals(entryStringInteger, typeResolver.resolveType(setEntryKV)); assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType()); } public void testOnObject() { TypeLiteral typeResolver = TypeLiteral.get(Object.class); assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType()); assertEquals(Object.class, typeResolver.getRawType()); // interfaces also resolve Object typeResolver = TypeLiteral.get(Types.setOf(Integer.class)); assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType()); } interface StringIntegerMap extends Map {} interface BetterMap extends Map {} interface BestMap extends BetterMap {} static class StringIntegerHashMap extends HashMap {} public void testGetSupertype() { TypeLiteral> listOfString = new TypeLiteral>() {}; assertEquals(Types.newParameterizedType(AbstractCollection.class, String.class), listOfString.getSupertype(AbstractCollection.class).getType()); TypeLiteral arrayListOfE = TypeLiteral.get(newParameterizedType( ArrayList.class, ArrayList.class.getTypeParameters())); assertEquals( newParameterizedType(AbstractCollection.class, ArrayList.class.getTypeParameters()), arrayListOfE.getSupertype(AbstractCollection.class).getType()); } public void testGetSupertypeForArraysAsList() { Class arraysAsListClass = Arrays.asList().getClass(); Type anotherE = arraysAsListClass.getTypeParameters()[0]; TypeLiteral type = TypeLiteral.get(newParameterizedType(AbstractList.class, anotherE)); assertEquals(newParameterizedType(AbstractCollection.class, anotherE), type.getSupertype(AbstractCollection.class).getType()); } public void testWildcards() throws NoSuchFieldException { TypeLiteral> ofString = new TypeLiteral>() {}; assertEquals(new TypeLiteral>() {}.getType(), ofString.getFieldType(Parameterized.class.getField("t")).getType()); assertEquals(new TypeLiteral>() {}.getType(), ofString.getFieldType(Parameterized.class.getField("extendsT")).getType()); assertEquals(new TypeLiteral>() {}.getType(), ofString.getFieldType(Parameterized.class.getField("superT")).getType()); } static class Parameterized { public List t; public List extendsT; public List superT; } // TODO(jessewilson): tests for tricky bounded types like public void testEqualsAndHashCode() throws IOException { TypeLiteral a1 = TypeLiteral.get(arrayListOfString); TypeLiteral a2 = TypeLiteral.get(arrayListOfString); TypeLiteral b = TypeLiteral.get(listOf(String.class)); assertEqualsBothWays(a1, a2); assertNotSerializable(a1); assertFalse(a1.equals(b)); } } guice-3.0/core/test/com/google/inject/Asserts.java0000644000175000017500000000752011460132772022057 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.NotSerializableException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import junit.framework.Assert; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; /** * @author jessewilson@google.com (Jesse Wilson) */ public class Asserts { private Asserts() {} /** * Fails unless {@code expected.equals(actual)}, {@code * actual.equals(expected)} and their hash codes are equal. This is useful * for testing the equals method itself. */ public static void assertEqualsBothWays(Object expected, Object actual) { assertNotNull(expected); assertNotNull(actual); assertTrue("expected.equals(actual)", expected.equals(actual)); assertTrue("actual.equals(expected)", actual.equals(expected)); assertEquals("hashCode", expected.hashCode(), actual.hashCode()); } /** * Fails unless {@code text} includes all {@code substrings}, in order. */ public static void assertContains(String text, String... substrings) { /*if[NO_AOP] // when we strip out bytecode manipulation, we lose the ability to generate some source lines. if (text.contains("(Unknown Source)")) { return; } end[NO_AOP]*/ int startingFrom = 0; for (String substring : substrings) { int index = text.indexOf(substring, startingFrom); assertTrue(String.format("Expected \"%s\" to contain substring \"%s\"", text, substring), index >= startingFrom); startingFrom = index + substring.length(); } String lastSubstring = substrings[substrings.length - 1]; assertTrue(String.format("Expected \"%s\" to contain substring \"%s\" only once),", text, lastSubstring), text.indexOf(lastSubstring, startingFrom) == -1); } /** * Fails unless {@code object} doesn't equal itself when reserialized. */ public static void assertEqualWhenReserialized(Object object) throws IOException { Object reserialized = reserialize(object); assertEquals(object, reserialized); assertEquals(object.hashCode(), reserialized.hashCode()); } /** * Fails unless {@code object} has the same toString value when reserialized. */ public static void assertSimilarWhenReserialized(Object object) throws IOException { Object reserialized = reserialize(object); assertEquals(object.toString(), reserialized.toString()); } public static E reserialize(E original) throws IOException { try { ByteArrayOutputStream out = new ByteArrayOutputStream(); new ObjectOutputStream(out).writeObject(original); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); @SuppressWarnings("unchecked") // the reserialized type is assignable E reserialized = (E) new ObjectInputStream(in).readObject(); return reserialized; } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static void assertNotSerializable(Object object) throws IOException { try { reserialize(object); Assert.fail(); } catch (NotSerializableException expected) { } } } guice-3.0/core/test/com/googlecode/0000755000175000017500000000000011460132764017144 5ustar drazzibdrazzibguice-3.0/core/test/com/googlecode/guice/0000755000175000017500000000000011471306152020234 5ustar drazzibdrazzibguice-3.0/core/test/com/googlecode/guice/Jsr330Test.java0000644000175000017500000003151211500107732022721 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.googlecode.guice; import com.google.inject.AbstractModule; import static com.google.inject.Asserts.assertContains; import com.google.inject.Binding; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Scope; import com.google.inject.Scopes; import com.google.inject.Stage; import com.google.inject.TypeLiteral; import com.google.inject.name.Names; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.util.Providers; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.util.Iterator; import java.util.Set; import static java.lang.annotation.RetentionPolicy.RUNTIME; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; import junit.framework.TestCase; public class Jsr330Test extends TestCase { private final B b = new B(); private final C c = new C(); private final D d = new D(); private final E e = new E(); @Override protected void setUp() throws Exception { J.nextInstanceId = 0; K.nextInstanceId = 0; } public void testInject() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(B.class).toInstance(b); bind(C.class).toInstance(c); bind(D.class).toInstance(d); bind(E.class).toInstance(e); bind(A.class); } }); A a = injector.getInstance(A.class); assertSame(b, a.b); assertSame(c, a.c); assertSame(d, a.d); assertSame(e, a.e); } public void testQualifiedInject() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(B.class).annotatedWith(Names.named("jodie")).toInstance(b); bind(C.class).annotatedWith(Red.class).toInstance(c); bind(D.class).annotatedWith(RED).toInstance(d); bind(E.class).annotatedWith(Names.named("jesse")).toInstance(e); bind(F.class); } }); F f = injector.getInstance(F.class); assertSame(b, f.b); assertSame(c, f.c); assertSame(d, f.d); assertSame(e, f.e); } public void testProviderInject() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(B.class).annotatedWith(Names.named("jodie")).toInstance(b); bind(C.class).toInstance(c); bind(D.class).annotatedWith(RED).toInstance(d); bind(E.class).toInstance(e); bind(G.class); } }); G g = injector.getInstance(G.class); assertSame(b, g.bProvider.get()); assertSame(c, g.cProvider.get()); assertSame(d, g.dProvider.get()); assertSame(e, g.eProvider.get()); } public void testScopeAnnotation() { final TestScope scope = new TestScope(); Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(B.class).in(scope); bind(C.class).in(TestScoped.class); bindScope(TestScoped.class, scope); } }); B b = injector.getInstance(B.class); assertSame(b, injector.getInstance(B.class)); assertSame(b, injector.getInstance(B.class)); C c = injector.getInstance(C.class); assertSame(c, injector.getInstance(C.class)); assertSame(c, injector.getInstance(C.class)); H h = injector.getInstance(H.class); assertSame(h, injector.getInstance(H.class)); assertSame(h, injector.getInstance(H.class)); scope.reset(); assertNotSame(b, injector.getInstance(B.class)); assertNotSame(c, injector.getInstance(C.class)); assertNotSame(h, injector.getInstance(H.class)); } public void testSingleton() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(B.class).in(Singleton.class); } }); B b = injector.getInstance(B.class); assertSame(b, injector.getInstance(B.class)); assertSame(b, injector.getInstance(B.class)); J j = injector.getInstance(J.class); assertSame(j, injector.getInstance(J.class)); assertSame(j, injector.getInstance(J.class)); } public void testEagerSingleton() { Guice.createInjector(Stage.PRODUCTION, new AbstractModule() { protected void configure() { bind(J.class); bind(K.class).in(Singleton.class); } }); assertEquals(1, J.nextInstanceId); assertEquals(1, K.nextInstanceId); } public void testScopesIsSingleton() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(J.class); bind(K.class).in(Singleton.class); } }); assertTrue(Scopes.isSingleton(injector.getBinding(J.class))); assertTrue(Scopes.isSingleton(injector.getBinding(K.class))); } public void testInjectingFinalFieldsIsForbidden() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(L.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Injected field " + L.class.getName() + ".b cannot be final."); } } public void testInjectingAbstractMethodsIsForbidden() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(M.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Injected method " + AbstractM.class.getName() + ".setB() cannot be abstract."); } } public void testInjectingMethodsWithTypeParametersIsForbidden() { try { Guice.createInjector(new AbstractModule() { protected void configure() { bind(N.class); } }); fail(); } catch (CreationException expected) { assertContains(expected.getMessage(), "1) Injected method " + N.class.getName() + ".setB() cannot declare type parameters of its own."); } } public void testInjectingMethodsWithNonVoidReturnTypes() { Guice.createInjector(new AbstractModule() { protected void configure() { bind(P.class); } }); } /** * This test verifies that we can compile bindings to provider instances * whose compile-time type implements javax.inject.Provider but not * com.google.inject.Provider. For binary compatibility, we don't (and won't) * support binding to instances of javax.inject.Provider. */ public void testBindProviderClass() { Injector injector = Guice.createInjector(new AbstractModule() { protected void configure() { bind(B.class).toProvider(BProvider.class); bind(B.class).annotatedWith(Names.named("1")).toProvider(BProvider.class); bind(B.class).annotatedWith(Names.named("2")).toProvider(Key.get(BProvider.class)); bind(B.class).annotatedWith(Names.named("3")).toProvider(TypeLiteral.get(BProvider.class)); } }); injector.getInstance(Key.get(B.class)); injector.getInstance(Key.get(B.class, Names.named("1"))); injector.getInstance(Key.get(B.class, Names.named("2"))); injector.getInstance(Key.get(B.class, Names.named("3"))); } public void testGuicify330Provider() { Provider jsr330Provider = new Provider() { public String get() { return "A"; } @Override public String toString() { return "jsr330Provider"; } }; com.google.inject.Provider guicified = Providers.guicify(jsr330Provider); assertEquals("guicified(jsr330Provider)", guicified.toString()); assertEquals("A", guicified.get()); // when you guicify the Guice-friendly, it's a no-op assertSame(guicified, Providers.guicify(guicified)); assertFalse(guicified instanceof HasDependencies); } public void testGuicifyWithDependencies() { Provider jsr330Provider = new Provider() { @Inject double d; int i; @Inject void injectMe(int i) { this.i = i; } public String get() { return d + "-" + i; } }; final com.google.inject.Provider guicified = Providers.guicify(jsr330Provider); assertTrue(guicified instanceof HasDependencies); Set> actual = ((HasDependencies)guicified).getDependencies(); validateDependencies(actual, jsr330Provider.getClass()); Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).toProvider(guicified); bind(int.class).toInstance(1); bind(double.class).toInstance(2.0d); } }); Binding binding = injector.getBinding(String.class); assertEquals("2.0-1", binding.getProvider().get()); validateDependencies(actual, jsr330Provider.getClass()); } private void validateDependencies(Set> actual, Class owner) { assertEquals(actual.toString(), 2, actual.size()); Dependency dDep = null; Dependency iDep = null; for(Dependency dep : actual) { if(dep.getKey().equals(Key.get(Double.class))) { dDep = dep; } else if(dep.getKey().equals(Key.get(Integer.class))) { iDep = dep; } } assertNotNull(dDep); assertNotNull(iDep); assertEquals(TypeLiteral.get(owner), dDep.getInjectionPoint().getDeclaringType()); assertEquals("d", dDep.getInjectionPoint().getMember().getName()); assertEquals(-1, dDep.getParameterIndex()); assertEquals(TypeLiteral.get(owner), iDep.getInjectionPoint().getDeclaringType()); assertEquals("injectMe", iDep.getInjectionPoint().getMember().getName()); assertEquals(0, iDep.getParameterIndex()); } static class A { final B b; @Inject C c; D d; E e; @Inject A(B b) { this.b = b; } @Inject void injectD(D d, E e) { this.d = d; this.e = e; } } static class B {} static class C {} static class D {} static class E {} static class F { final B b; @Inject @Red C c; D d; E e; @Inject F(@Named("jodie") B b) { this.b = b; } @Inject void injectD(@Red D d, @Named("jesse") E e) { this.d = d; this.e = e; } } @Qualifier @Retention(RUNTIME) @interface Red {} public static final Red RED = new Red() { public Class annotationType() { return Red.class; } @Override public boolean equals(Object obj) { return obj instanceof Red; } @Override public int hashCode() { return 0; } }; static class G { final Provider bProvider; @Inject Provider cProvider; Provider dProvider; Provider eProvider; @Inject G(@Named("jodie") Provider bProvider) { this.bProvider = bProvider; } @Inject void injectD(@Red Provider dProvider, Provider eProvider) { this.dProvider = dProvider; this.eProvider = eProvider; } } @javax.inject.Scope @Retention(RUNTIME) @interface TestScoped {} static class TestScope implements Scope { private int now = 0; public com.google.inject.Provider scope(Key key, final com.google.inject.Provider unscoped) { return new com.google.inject.Provider() { private T value; private int snapshotTime = -1; public T get() { if (snapshotTime != now) { value = unscoped.get(); snapshotTime = now; } return value; } }; } public void reset() { now++; } } @TestScoped static class H {} @Singleton static class J { static int nextInstanceId = 0; int instanceId = nextInstanceId++; } static class K { static int nextInstanceId = 0; int instanceId = nextInstanceId++; } static class L { @Inject final B b = null; } static abstract class AbstractM { @Inject abstract void setB(B b); } static class M extends AbstractM { void setB(B b) {} } static class N { @Inject void setB(B b) {} } static class P { @Inject B setB(B b) { return b; } } static class BProvider implements Provider { public B get() { return new B(); } } } guice-3.0/core/test/com/googlecode/guice/StrictContainerTestSuite.java0000644000175000017500000000763111460132764026077 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.googlecode.guice; import com.google.inject.AllTests; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.MapMakerTestSuite; import com.google.inject.internal.util.MapMakerTestSuite.ReferenceMapTest; import com.google.inject.internal.util.MapMakerTestSuite.ComputingTest; import java.io.FilePermission; import java.security.AccessControlException; import java.security.Permission; import java.util.Arrays; import java.util.PropertyPermission; import java.util.Set; import junit.framework.Test; /** * Runs a subset of our tests in a more secure environment. It loads the tests in another * classloader, and runs them with a specific security manager. Note that no security manager is in * place when test instances are constructed. * * @author jessewilson@google.com (Jesse Wilson) */ public class StrictContainerTestSuite { /** Tests tests require background threads to pass, which the strict container forbids */ private static final Set SUPPRESSED_TEST_NAMES = ImmutableSet.of( "testValueCleanupWithWeakKey(" + ReferenceMapTest.class.getName() + ")", "testValueCleanupWithSoftKey(" + ReferenceMapTest.class.getName() + ")", "testKeyCleanupWithWeakKey(" + ReferenceMapTest.class.getName() + ")", "testKeyCleanupWithSoftKey(" + ReferenceMapTest.class.getName() + ")", "testKeyCleanupWithWeakValue(" + ReferenceMapTest.class.getName() + ")", "testKeyCleanupWithSoftValue(" + ReferenceMapTest.class.getName() + ")", "testInternedValueCleanupWithWeakKey(" + ReferenceMapTest.class.getName() + ")", "testInternedValueCleanupWithSoftKey(" + ReferenceMapTest.class.getName() + ")", "testInternedKeyCleanupWithWeakValue(" + ReferenceMapTest.class.getName() + ")", "testInternedKeyCleanupWithSoftValue(" + ReferenceMapTest.class.getName() + ")", "testSleepConcurrency(" + ComputingTest.class.getName() + ")", "testBusyConcurrency(" + ComputingTest.class.getName() + ")", "testFastConcurrency(" + ComputingTest.class.getName() + ")", "testSleepCanonical(" + ComputingTest.class.getName() + ")", "testBusyCanonical(" + ComputingTest.class.getName() + ")", "testFastCanonical(" + ComputingTest.class.getName() + ")" ); public static Test suite() { SecurityManager securityManager = new SecurityManager() { @Override public void checkPermission(Permission permission) { if (permission instanceof FilePermission || permission instanceof PropertyPermission) { return; // avoid creating a stacktrace for common permissions } String stacktrace = Arrays.toString(new Throwable().getStackTrace()); if (stacktrace.contains("Thread.") || stacktrace.contains(".getSystemClassLoader(")) { throw new AccessControlException("StrictContainerTestSuite forbids this!"); } } @Override public void checkPermission(Permission permission, Object context) { checkPermission(permission); } }; StrictContainerTestSuiteBuilder builder = new StrictContainerTestSuiteBuilder(securityManager); /*if[AOP]*/ builder.add(BytecodeGenTest.class.getName()); /*end[AOP]*/ builder.addSuite(MapMakerTestSuite.class.getName()); return AllTests.removeSuppressedTests(builder.build(), SUPPRESSED_TEST_NAMES); } } guice-3.0/core/test/com/googlecode/guice/PackageVisibilityTestModule.java0000644000175000017500000000116111460132764026513 0ustar drazzibdrazzibpackage com.googlecode.guice; import com.google.inject.AbstractModule; import com.google.inject.Inject; public class PackageVisibilityTestModule extends AbstractModule { @Override protected void configure() { bind(PackagePrivateInterface.class).to(PackagePrivateImpl.class); } public static class PublicUserOfPackagePrivate { @Inject public PublicUserOfPackagePrivate(PackagePrivateInterface ppi) {} @Inject public void acceptPackagePrivateParameter(PackagePrivateInterface ppi) {} } interface PackagePrivateInterface {} static class PackagePrivateImpl implements PackagePrivateInterface {} } guice-3.0/core/test/com/googlecode/guice/GuiceTck.java0000644000175000017500000000357211460132764022610 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.googlecode.guice; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Provides; import javax.inject.Named; import junit.framework.Test; import org.atinject.tck.Tck; import org.atinject.tck.auto.Car; import org.atinject.tck.auto.Convertible; import org.atinject.tck.auto.Drivers; import org.atinject.tck.auto.DriversSeat; import org.atinject.tck.auto.Engine; import org.atinject.tck.auto.FuelTank; import org.atinject.tck.auto.Seat; import org.atinject.tck.auto.Tire; import org.atinject.tck.auto.V8Engine; import org.atinject.tck.auto.accessories.Cupholder; import org.atinject.tck.auto.accessories.SpareTire; public class GuiceTck { public static Test suite() { return Tck.testsFor(Guice.createInjector(new AbstractModule() { protected void configure() { bind(Car.class).to(Convertible.class); bind(Seat.class).annotatedWith(Drivers.class).to(DriversSeat.class); bind(Engine.class).to(V8Engine.class); bind(Cupholder.class); bind(Tire.class); bind(FuelTank.class); requestStaticInjection(Convertible.class, SpareTire.class); } @Provides @Named("spare") Tire provideSpareTire(SpareTire spare) { return spare; } }).getInstance(Car.class), true, true); } } guice-3.0/core/test/com/googlecode/guice/bundle/0000755000175000017500000000000011460132764021511 5ustar drazzibdrazzibguice-3.0/core/test/com/googlecode/guice/bundle/OSGiTestActivator.java0000644000175000017500000002313011460132764025671 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.googlecode.guice.bundle; import static com.google.inject.name.Names.named; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Random; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.matcher.AbstractMatcher; /** * Test Guice from inside an OSGi bundle activator. * * @author mcculls@gmail.com (Stuart McCulloch) */ @SuppressWarnings("unused") public class OSGiTestActivator implements BundleActivator { // varying visibilities to test our code-generation support public static class _ {} public interface A {} protected interface B {} interface C {} private interface D {} public static class AA implements A { public AA() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } protected static class AB implements A { public AB() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } static class AC implements A { public AC() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } private static class AD implements A { public AD() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } public static class BA implements B { protected BA() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } protected static class BB implements B { protected BB() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } static class BC implements B { protected BC() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } private static class BD implements B { protected BD() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } public static class CA implements C { CA() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } protected static class CB implements C { CB() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } static class CC implements C { CC() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } private static class CD implements C { CD() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } public static class DA implements D { @Inject private DA() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } protected static class DB implements D { @Inject private DB() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } static class DC implements D { @Inject private DC() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } private static class DD implements D { private DD() {} @Inject public void setA(_ _) {} @Inject protected void setB(_ _) {} @Inject void setC(_ _) {} @Inject private void setD(_ _) {} @Inject public _ a; @Inject protected _ b; @Inject _ c; @Inject private _ d; } enum Visibility { PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE } static final Class[] TEST_CLAZZES = {A.class, B.class, C.class, D.class}; // registers all the class combinations static class TestModule extends AbstractModule { final Bundle bundle; TestModule(Bundle bundle) { this.bundle = bundle; } @Override @SuppressWarnings("unchecked") protected void configure() { for (Class api : TEST_CLAZZES) { for (Visibility visibility : Visibility.values()) { try { // this registers: A + PUBLIC -> AA, A + PROTECTED -> AB, etc... String suffix = TEST_CLAZZES[visibility.ordinal()].getSimpleName(); Class imp = bundle.loadClass(api.getName() + suffix); bind(api).annotatedWith(named(visibility.name())).to(imp); } catch (ClassNotFoundException e) { throw new RuntimeException("Unable to load test class", e); } } } } } /*if[AOP]*/ // applies method-interception to classes with enough visibility static class InterceptorModule extends AbstractModule { @Override protected void configure() { bindInterceptor(new AbstractMatcher>() { public boolean matches(Class clazz) { try { // the class and constructor must be visible int clazzModifiers = clazz.getModifiers(); int ctorModifiers = clazz.getConstructor().getModifiers(); return (clazzModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0 && (ctorModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0; } catch (NoSuchMethodException e) { return false; } } }, new AbstractMatcher() { public boolean matches(Method method) { // the intercepted method must also be visible int methodModifiers = method.getModifiers(); return (methodModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0; } }, new org.aopalliance.intercept.MethodInterceptor() { public Object invoke(org.aopalliance.intercept.MethodInvocation mi) throws Throwable { return mi.proceed(); } }); } } /*end[AOP]*/ // called from OSGi when bundle starts public void start(BundleContext context) throws BundleException { final Bundle bundle = context.getBundle(); Injector injector = Guice.createInjector(new TestModule(bundle)); /*if[AOP]*/ Injector aopInjector = Guice.createInjector(new TestModule(bundle), new InterceptorModule()); /*end[AOP]*/ // test code-generation support for (Class api : TEST_CLAZZES) { for (Visibility vis : Visibility.values()) { injector.getInstance(Key.get(api, named(vis.name()))); /*if[AOP]*/ aopInjector.getInstance(Key.get(api, named(vis.name()))); /*end[AOP]*/ } } // test injection of system class (issue 343) injector.getInstance(Random.class); /*if[AOP]*/ aopInjector.getInstance(Random.class); /*end[AOP]*/ } // called from OSGi when bundle stops public void stop(BundleContext context) {} } guice-3.0/core/test/com/googlecode/guice/StrictContainerTestSuiteBuilder.java0000644000175000017500000001205011471306152027371 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.googlecode.guice; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.Collections; import java.util.Enumeration; import junit.extensions.TestDecorator; import junit.framework.Test; import junit.framework.TestResult; import junit.framework.TestSuite; /** * Builds a test suite whose tests are loaded in a private classloader and run them with a security * manager. * * @author jessewilson@google.com (Jesse Wilson) */ public class StrictContainerTestSuiteBuilder { private final ClassLoader classLoader = new NonSystemClassLoader(); private final SecurityManager securityManager; private final TestSuite testSuite = new TestSuite("StrictContainer"); public StrictContainerTestSuiteBuilder(SecurityManager securityManager) { this.securityManager = securityManager; } public void add(String testClassName) { try { Class testClass = classLoader.loadClass(testClassName); testSuite.addTest(securityManaged(new TestSuite(testClass))); } catch (Exception e) { testSuite.addTest(new SuiteConstructionError(testClassName, e)); } } public void addSuite(String suiteClassname) { try { Class suiteClass = classLoader.loadClass(suiteClassname); Test testSuite = (Test) suiteClass.getMethod("suite").invoke(null); this.testSuite.addTest(securityManaged(testSuite)); } catch (Exception e) { testSuite.addTest(new SuiteConstructionError(suiteClassname, e)); } } public TestSuite build() { return testSuite; } /** * A classloader that reloads everything outside of the JDK. */ static class NonSystemClassLoader extends URLClassLoader { public NonSystemClassLoader() { super(new URL[0]); for (final String element : System.getProperty("java.class.path").split(File.pathSeparator)) { try { // is it a remote/local URL? addURL(new URL(element)); } catch (MalformedURLException e1) { // nope - perhaps it's a filename? try { addURL(new File(element).toURI().toURL()); } catch (MalformedURLException e2) { throw new RuntimeException(e1); } } } } @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { // check our local cache to avoid duplicates synchronized (this) { Class clazz = findLoadedClass(name); if (clazz != null) { return clazz; } } if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("junit.") || name.startsWith("sun.") || name.startsWith("com.sun.") || name.contains("cglib")) { return super.loadClass(name, resolve); } Class clazz = findClass(name); if (resolve) { resolveClass(clazz); } return clazz; } } /** * Returns a test that sets up and tears down a security manager while it's run. */ public Test securityManaged(Test test) { if (test instanceof TestSuite) { TestSuite suite = (TestSuite) test; TestSuite result = new TestSuite(suite.getName()); @SuppressWarnings("unchecked") // a test suite's elements are tests Enumeration children = (Enumeration) suite.tests(); for (Test child : Collections.list(children)) { result.addTest(securityManaged(child)); } return result; } else { return new TestDecorator(test) { public void run(TestResult testResult) { SecurityManager originalSecurityManager = System.getSecurityManager(); System.setSecurityManager(securityManager); try { basicRun(testResult); } finally { testResult.endTest(this); System.setSecurityManager(originalSecurityManager); } } }; } } /** * A simple test that always fails with an exception. */ private static class SuiteConstructionError implements Test { private String className; private final Exception cause; public SuiteConstructionError(String className, Exception cause) { this.className = className; this.cause = cause; } public void run(TestResult testResult) { testResult.addError(this, cause); } public int countTestCases() { return 1; } @Override public String toString() { return className; } } } guice-3.0/core/test/com/googlecode/guice/BytecodeGenTest.java0000644000175000017500000002447411471047404024144 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.googlecode.guice; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import static com.google.inject.matcher.Matchers.any; import com.googlecode.guice.PackageVisibilityTestModule.PublicUserOfPackagePrivate; import java.io.File; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import junit.framework.TestCase; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * This test is in a separate package so we can test package-level visibility * with confidence. * * @author mcculls@gmail.com (Stuart McCulloch) */ public class BytecodeGenTest extends TestCase { private final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); private final Module interceptorModule = new AbstractModule() { protected void configure() { bindInterceptor(any(), any(), new MethodInterceptor() { public Object invoke(MethodInvocation chain) throws Throwable { return chain.proceed() + " WORLD"; } }); } }; private final Module noopInterceptorModule = new AbstractModule() { protected void configure() { bindInterceptor(any(), any(), new MethodInterceptor() { public Object invoke(MethodInvocation chain) throws Throwable { return chain.proceed(); } }); } }; public void testPackageVisibility() { Injector injector = Guice.createInjector(new PackageVisibilityTestModule()); injector.getInstance(PublicUserOfPackagePrivate.class); // This must pass. } public void testInterceptedPackageVisibility() { Injector injector = Guice.createInjector(interceptorModule, new PackageVisibilityTestModule()); injector.getInstance(PublicUserOfPackagePrivate.class); // This must pass. } public void testEnhancerNaming() { Injector injector = Guice.createInjector(interceptorModule, new PackageVisibilityTestModule()); PublicUserOfPackagePrivate pupp = injector.getInstance(PublicUserOfPackagePrivate.class); assertTrue(pupp.getClass().getName().startsWith( PublicUserOfPackagePrivate.class.getName() + "$$EnhancerByGuice$$")); } // TODO(sameb): Figure out how to test FastClass naming tests. /** * Custom URL classloader with basic visibility rules */ static class TestVisibilityClassLoader extends URLClassLoader { boolean hideInternals; public TestVisibilityClassLoader(boolean hideInternals) { super(new URL[0]); this.hideInternals = hideInternals; final String[] classpath = System.getProperty("java.class.path").split(File.pathSeparator); for (final String element : classpath) { try { // is it a remote/local URL? addURL(new URL(element)); } catch (final MalformedURLException e1) { try { // nope - perhaps it's a filename? addURL(new File(element).toURI().toURL()); } catch (final MalformedURLException e2) { throw new RuntimeException(e1); } } } } /** * Classic parent-delegating classloaders are meant to override findClass. * However, non-delegating classloaders (as used in OSGi) instead override * loadClass to provide support for "class-space" separation. */ @Override protected Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { synchronized (this) { // check our local cache to avoid duplicates final Class clazz = findLoadedClass(name); if (clazz != null) { return clazz; } } if (name.startsWith("java.")) { // standard bootdelegation of java.* return super.loadClass(name, resolve); } else if (!name.contains(".internal.") && !name.contains(".cglib.")) { /* * load public and test classes directly from the classpath - we don't * delegate to our parent because then the loaded classes would also be * able to see private internal Guice classes, as they are also loaded * by the parent classloader. */ final Class clazz = findClass(name); if (resolve) { resolveClass(clazz); } return clazz; } // hide internal non-test classes if (hideInternals) { throw new ClassNotFoundException(); } return super.loadClass(name, resolve); } } /** as loaded by another class loader */ private Class proxyTestClass; private Class realClass; private Module testModule; @SuppressWarnings("unchecked") protected void setUp() throws Exception { super.setUp(); ClassLoader testClassLoader = new TestVisibilityClassLoader(true); proxyTestClass = (Class) testClassLoader.loadClass(ProxyTest.class.getName()); realClass = (Class) testClassLoader.loadClass(ProxyTestImpl.class.getName()); testModule = new AbstractModule() { public void configure() { bind(proxyTestClass).to(realClass); } }; } interface ProxyTest { String sayHello(); } /** * Note: this class must be marked as public or protected so that the Guice * custom classloader will intercept it. Private and implementation classes * are not intercepted by the custom classloader. * * @see com.google.inject.internal.BytecodeGen.Visibility */ public static class ProxyTestImpl implements ProxyTest { static { //System.out.println(ProxyTestImpl.class.getClassLoader()); } public String sayHello() { return "HELLO"; } } public void testProxyClassLoading() throws Exception { Object testObject = Guice.createInjector(interceptorModule, testModule) .getInstance(proxyTestClass); // verify method interception still works Method m = realClass.getMethod("sayHello"); assertEquals("HELLO WORLD", m.invoke(testObject)); } public void testSystemClassLoaderIsUsedIfProxiedClassUsesIt() { ProxyTest testProxy = Guice.createInjector(interceptorModule, new Module() { public void configure(Binder binder) { binder.bind(ProxyTest.class).to(ProxyTestImpl.class); } }).getInstance(ProxyTest.class); if (ProxyTest.class.getClassLoader() == systemClassLoader) { assertSame(testProxy.getClass().getClassLoader(), systemClassLoader); } else { assertNotSame(testProxy.getClass().getClassLoader(), systemClassLoader); } } public void testProxyClassUnloading() { Object testObject = Guice.createInjector(interceptorModule, testModule) .getInstance(proxyTestClass); assertNotNull(testObject.getClass().getClassLoader()); assertNotSame(testObject.getClass().getClassLoader(), systemClassLoader); // take a weak reference to the generated proxy class Reference> clazzRef = new WeakReference>(testObject.getClass()); assertNotNull(clazzRef.get()); // null the proxy testObject = null; /* * this should be enough to queue the weak reference * unless something is holding onto it accidentally. */ String[] buf; System.gc(); buf = new String[8 * 1024 * 1024]; buf = null; System.gc(); buf = new String[8 * 1024 * 1024]; buf = null; System.gc(); buf = new String[8 * 1024 * 1024]; buf = null; System.gc(); buf = new String[8 * 1024 * 1024]; buf = null; System.gc(); // This test could be somewhat flaky when the GC isn't working. // If it fails, run the test again to make sure it's failing reliably. assertNull(clazzRef.get()); } public void testProxyingPackagePrivateMethods() { Injector injector = Guice.createInjector(interceptorModule); assertEquals("HI WORLD", injector.getInstance(PackageClassPackageMethod.class).sayHi()); assertEquals("HI WORLD", injector.getInstance(PublicClassPackageMethod.class).sayHi()); assertEquals("HI WORLD", injector.getInstance(ProtectedClassProtectedMethod.class).sayHi()); } static class PackageClassPackageMethod { String sayHi() { return "HI"; } } public static class PublicClassPackageMethod { String sayHi() { return "HI"; } } protected static class ProtectedClassProtectedMethod { protected String sayHi() { return "HI"; } } static class Hidden { } public static class HiddenMethodReturn { public Hidden method() { return new Hidden(); } } public static class HiddenMethodParameter { public void method(Hidden h) { } } public void testClassLoaderBridging() throws Exception { ClassLoader testClassLoader = new TestVisibilityClassLoader(false); Class hiddenMethodReturnClass = testClassLoader.loadClass(HiddenMethodReturn.class.getName()); Class hiddenMethodParameterClass = testClassLoader.loadClass(HiddenMethodParameter.class.getName()); Injector injector = Guice.createInjector(noopInterceptorModule); Class hiddenClass = testClassLoader.loadClass(Hidden.class.getName()); Constructor ctor = hiddenClass.getDeclaredConstructor(); ctor.setAccessible(true); // don't use bridging for proxies with private parameters Object o1 = injector.getInstance(hiddenMethodParameterClass); o1.getClass().getDeclaredMethod("method", hiddenClass).invoke(o1, ctor.newInstance()); // don't use bridging for proxies with private return types Object o2 = injector.getInstance(hiddenMethodReturnClass); o2.getClass().getDeclaredMethod("method").invoke(o2); } } guice-3.0/core/test/com/googlecode/guice/OSGiContainerTest.java0000644000175000017500000001306311460132764024412 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.googlecode.guice; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Iterator; import java.util.Properties; import javax.imageio.spi.ServiceRegistry; import junit.framework.TestCase; import org.osgi.framework.BundleContext; import org.osgi.framework.launch.Framework; import org.osgi.framework.launch.FrameworkFactory; import aQute.bnd.main.bnd; import com.googlecode.guice.bundle.OSGiTestActivator; /** * Run various tests inside one or more OSGi containers. * * @author mcculls@gmail.com (Stuart McCulloch) */ public class OSGiContainerTest extends TestCase { // build properties passed from Ant static final String VERSION = System.getProperty("version", "snapshot"); static final String BUILD_DIR = System.getProperty("build.dir", "build"); static final String BUILD_DIST_DIR = BUILD_DIR + "/dist"; static final String BUILD_TEST_DIR = BUILD_DIR + "/test"; static final String GUICE_JAR = BUILD_DIST_DIR + "/guice-" + VERSION + ".jar"; /*if[AOP]*/ static final String AOPALLIANCE_JAR = System.getProperty("aopalliance.jar", "lib/aopalliance.jar"); /*end[AOP]*/ static final String JAVAX_INJECT_JAR = System.getProperty("javax.inject.jar", "lib/javax.inject.jar"); // dynamically build test bundles @Override protected void setUp() throws Exception { // verify properties assertTrue(failMsg(), new File(BUILD_DIR).isDirectory()); assertTrue(failMsg(), new File(GUICE_JAR).isFile()); /*if[AOP]*/ assertTrue(failMsg(), new File(AOPALLIANCE_JAR).isFile()); /*end[AOP]*/ assertTrue(failMsg(), new File(JAVAX_INJECT_JAR).isFile()); Properties instructions = new Properties(); /*if[AOP]*/ // aopalliance is an API bundle --> export the full API instructions.setProperty("Export-Package", "org.aopalliance.*"); buildBundle("aopalliance", instructions, AOPALLIANCE_JAR); instructions.clear(); /*end[AOP]*/ // javax.inject is an API bundle --> export the full API instructions.setProperty("Export-Package", "javax.inject.*"); buildBundle("javax.inject", instructions, JAVAX_INJECT_JAR); instructions.clear(); // strict imports to make sure test bundle only has access to these packages instructions.setProperty("Import-Package", "org.osgi.framework," /*if[AOP]*/ + "org.aopalliance.intercept," /*end[AOP]*/ + "com.google.inject(|.binder|.matcher|.name)"); // test bundle should only contain the local test classes, nothing else instructions.setProperty("Bundle-Activator", OSGiTestActivator.class.getName()); instructions.setProperty("Private-Package", OSGiTestActivator.class.getPackage().getName()); buildBundle("osgitests", instructions, BUILD_TEST_DIR); instructions.clear(); } // build an OSGi bundle at runtime private static void buildBundle(String name, Properties instructions, String classpath) throws IOException { // write BND instructions to temporary test directory String bndFileName = BUILD_TEST_DIR + '/' + name + ".bnd"; OutputStream os = new BufferedOutputStream(new FileOutputStream(bndFileName)); instructions.store(os, "BND instructions"); os.close(); // assemble bundle, use -failok switch to avoid early exit bnd.main(new String[]{"-failok", "build", "-classpath", classpath, bndFileName}); } private String failMsg() { return "This test may fail if it is not run from ant, or if it is not run after ant has " + "compiled & built jars. This is because the test is validating that the Guice jar " + "is properly setup to load in an OSGi container"; } //This test may fail if it is not run from ant, or if it is not run after ant has //compiled & built jars. This is because the test is validating that the Guice jar //is properly setup to load in an OSGi container public void testGuiceWorksInOSGiContainer() throws Throwable { // ask framework to clear cache on startup Properties properties = new Properties(); properties.setProperty("org.osgi.framework.storage", BUILD_TEST_DIR + "/bundle.cache"); properties.setProperty("org.osgi.framework.storage.clean", "onFirstInit"); // test each available OSGi framework in turn Iterator f = ServiceRegistry.lookupProviders(FrameworkFactory.class); while (f.hasNext()) { Framework framework = f.next().newFramework(properties); framework.start(); BundleContext systemContext = framework.getBundleContext(); // load all the necessary bundles and start the OSGi test bundle /*if[AOP]*/ systemContext.installBundle("reference:file:" + BUILD_TEST_DIR + "/aopalliance.jar"); /*end[AOP]*/ systemContext.installBundle("reference:file:" + BUILD_TEST_DIR + "/javax.inject.jar"); systemContext.installBundle("reference:file:" + GUICE_JAR); systemContext.installBundle("reference:file:" + BUILD_TEST_DIR + "/osgitests.jar").start(); framework.stop(); } } } guice-3.0/core/src/0000755000175000017500000000000011460132772014066 5ustar drazzibdrazzibguice-3.0/core/src/com/0000755000175000017500000000000011460132772014644 5ustar drazzibdrazzibguice-3.0/core/src/com/google/0000755000175000017500000000000011460132772016120 5ustar drazzibdrazzibguice-3.0/core/src/com/google/inject/0000755000175000017500000000000011531414136017370 5ustar drazzibdrazzibguice-3.0/core/src/com/google/inject/PrivateBinder.java0000644000175000017500000000334211460133000022760 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.binder.AnnotatedElementBuilder; /** * Returns a binder whose configuration information is hidden from its environment by default. See * {@link com.google.inject.PrivateModule PrivateModule} for details. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface PrivateBinder extends Binder { /** Makes the binding for {@code key} available to the enclosing environment */ void expose(Key key); /** * Makes a binding for {@code type} available to the enclosing environment. Use {@link * com.google.inject.binder.AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a * binding annotation. */ AnnotatedElementBuilder expose(Class type); /** * Makes a binding for {@code type} available to the enclosing environment. Use {@link * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a * binding annotation. */ AnnotatedElementBuilder expose(TypeLiteral type); PrivateBinder withSource(Object source); PrivateBinder skipSources(Class... classesToSkip); } guice-3.0/core/src/com/google/inject/package-info.java0000644000175000017500000000330611460133000022546 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Google Guice (pronounced "juice") is an ultra-lightweight dependency * injection framework. Please refer to the Guice * User's Guide * for a gentle introduction. * *

The principal public APIs in this package are: * *

*
{@link com.google.inject.Inject} *
The annotation you will use in your implementation classes to tell Guice * where and how it should send in ("inject") the objects you depend on * (your "dependencies"). * *
{@link com.google.inject.Module} *
The interface you will implement in order to specify "bindings" -- * instructions for how Guice should handle injection -- for a particular * set of interfaces. * *
{@link com.google.inject.Binder} *
The object that Guice passes into your {@link com.google.inject.Module} * to collect these bindings. * *
{@link com.google.inject.Provider} *
The interface you will implement when you need to customize exactly how * Guice creates instances for a particular binding. * *
* */ package com.google.inject;guice-3.0/core/src/com/google/inject/Guice.java0000644000175000017500000000605711501200322021262 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import java.util.Arrays; import com.google.inject.internal.InternalInjectorCreator; /** * The entry point to the Guice framework. Creates {@link Injector}s from * {@link Module}s. * *

Guice supports a model of development that draws clear boundaries between * APIs, Implementations of these APIs, Modules which configure these * implementations, and finally Applications which consist of a collection of * Modules. It is the Application, which typically defines your {@code main()} * method, that bootstraps the Guice Injector using the {@code Guice} class, as * in this example: *

 *     public class FooApplication {
 *       public static void main(String[] args) {
 *         Injector injector = Guice.createInjector(
 *             new ModuleA(),
 *             new ModuleB(),
 *             . . .
 *             new FooApplicationFlagsModule(args)
 *         );
 *
 *         // Now just bootstrap the application and you're done
 *         FooStarter starter = injector.getInstance(FooStarter.class);
 *         starter.runApplication();
 *       }
 *     }
 * 
*/ public final class Guice { private Guice() {} /** * Creates an injector for the given set of modules. * * @throws CreationException if one or more errors occur during injector * construction */ public static Injector createInjector(Module... modules) { return createInjector(Arrays.asList(modules)); } /** * Creates an injector for the given set of modules. * * @throws CreationException if one or more errors occur during injector * creation */ public static Injector createInjector(Iterable modules) { return createInjector(Stage.DEVELOPMENT, modules); } /** * Creates an injector for the given set of modules, in a given development * stage. * * @throws CreationException if one or more errors occur during injector * creation. */ public static Injector createInjector(Stage stage, Module... modules) { return createInjector(stage, Arrays.asList(modules)); } /** * Creates an injector for the given set of modules, in a given development * stage. * * @throws CreationException if one or more errors occur during injector * construction */ public static Injector createInjector(Stage stage, Iterable modules) { return new InternalInjectorCreator() .stage(stage) .addModules(modules) .build(); } } guice-3.0/core/src/com/google/inject/ScopeAnnotation.java0000644000175000017500000000247711460133000023336 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Annotates annotations which are used for scoping. Only one such annotation * may apply to a single implementation class. You must also annotate scope * annotations with {@code @Retention(RUNTIME)}. For example: * *
 *   {@code @}Retention(RUNTIME)
 *   {@code @}Target(TYPE, METHOD)
 *   {@code @}ScopeAnnotation
 *   public {@code @}interface SessionScoped {}
 * 
* * @author crazybob@google.com (Bob Lee) */ @Target(ANNOTATION_TYPE) @Retention(RUNTIME) public @interface ScopeAnnotation {} guice-3.0/core/src/com/google/inject/OutOfScopeException.java0000644000175000017500000000224311460133000024126 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; /** * Thrown from {@link Provider#get} when an attempt is made to access a scoped * object while the scope in question is not currently active. * * @author kevinb@google.com (Kevin Bourrillion) * @since 2.0 */ public final class OutOfScopeException extends RuntimeException { public OutOfScopeException(String message) { super(message); } public OutOfScopeException(String message, Throwable cause) { super(message, cause); } public OutOfScopeException(Throwable cause) { super(cause); } } guice-3.0/core/src/com/google/inject/name/0000755000175000017500000000000011460132772020314 5ustar drazzibdrazzibguice-3.0/core/src/com/google/inject/name/package-info.java0000644000175000017500000000125111460132772023502 0ustar drazzibdrazzib/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Support for binding to string-based names. */ package com.google.inject.name;guice-3.0/core/src/com/google/inject/name/NamedImpl.java0000644000175000017500000000300511460132772023023 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.name; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.io.Serializable; import java.lang.annotation.Annotation; class NamedImpl implements Named, Serializable { private final String value; public NamedImpl(String value) { this.value = checkNotNull(value, "name"); } public String value() { return this.value; } public int hashCode() { // This is specified in java.lang.Annotation. return (127 * "value".hashCode()) ^ value.hashCode(); } public boolean equals(Object o) { if (!(o instanceof Named)) { return false; } Named other = (Named) o; return value.equals(other.value()); } public String toString() { return "@" + Named.class.getName() + "(value=" + value + ")"; } public Class annotationType() { return Named.class; } private static final long serialVersionUID = 0; } guice-3.0/core/src/com/google/inject/name/Named.java0000644000175000017500000000210111460132772022175 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.name; import com.google.inject.BindingAnnotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Annotates named things. * * @author crazybob@google.com (Bob Lee) */ @Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation public @interface Named { String value(); } guice-3.0/core/src/com/google/inject/name/Names.java0000644000175000017500000000427711460132772022234 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.name; import com.google.inject.Binder; import com.google.inject.Key; import java.util.Enumeration; import java.util.Map; import java.util.Properties; /** * Utility methods for use with {@code @}{@link Named}. * * @author crazybob@google.com (Bob Lee) */ public class Names { private Names() {} /** * Creates a {@link Named} annotation with {@code name} as the value. */ public static Named named(String name) { return new NamedImpl(name); } /** * Creates a constant binding to {@code @Named(key)} for each entry in * {@code properties}. */ public static void bindProperties(Binder binder, Map properties) { binder = binder.skipSources(Names.class); for (Map.Entry entry : properties.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); binder.bind(Key.get(String.class, new NamedImpl(key))).toInstance(value); } } /** * Creates a constant binding to {@code @Named(key)} for each property. This * method binds all properties including those inherited from * {@link Properties#defaults defaults}. */ public static void bindProperties(Binder binder, Properties properties) { binder = binder.skipSources(Names.class); // use enumeration to include the default properties for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) { String propertyName = (String) e.nextElement(); String value = properties.getProperty(propertyName); binder.bind(Key.get(String.class, new NamedImpl(propertyName))).toInstance(value); } } } guice-3.0/core/src/com/google/inject/MembersInjector.java0000644000175000017500000000270711460133000023316 0ustar drazzibdrazzib/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; /** * Injects dependencies into the fields and methods on instances of type {@code T}. Ignores the * presence or absence of an injectable constructor. * * @param type to inject members of * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface MembersInjector { /** * Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or * absence of an injectable constructor. * *

Whenever Guice creates an instance, it performs this injection automatically (after first * performing constructor injection), so if you're able to let Guice create all your objects for * you, you'll never need to use this method. * * @param instance to inject members on. May be {@code null}. */ void injectMembers(T instance); } guice-3.0/core/src/com/google/inject/AbstractModule.java0000644000175000017500000001511111531414136023143 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.binder.AnnotatedConstantBindingBuilder; import com.google.inject.binder.LinkedBindingBuilder; import static com.google.inject.internal.util.Preconditions.checkNotNull; import static com.google.inject.internal.util.Preconditions.checkState; import com.google.inject.matcher.Matcher; import com.google.inject.spi.Message; import com.google.inject.spi.TypeConverter; import com.google.inject.spi.TypeListener; import java.lang.annotation.Annotation; import java.lang.reflect.Method; /** * A support class for {@link Module}s which reduces repetition and results in * a more readable configuration. Simply extend this class, implement {@link * #configure()}, and call the inherited methods which mirror those found in * {@link Binder}. For example: * *

 * public class MyModule extends AbstractModule {
 *   protected void configure() {
 *     bind(Service.class).to(ServiceImpl.class).in(Singleton.class);
 *     bind(CreditCardPaymentService.class);
 *     bind(PaymentService.class).to(CreditCardPaymentService.class);
 *     bindConstant().annotatedWith(Names.named("port")).to(8080);
 *   }
 * }
 * 
* * @author crazybob@google.com (Bob Lee) */ public abstract class AbstractModule implements Module { Binder binder; public final synchronized void configure(Binder builder) { checkState(this.binder == null, "Re-entry is not allowed."); this.binder = checkNotNull(builder, "builder"); try { configure(); } finally { this.binder = null; } } /** * Configures a {@link Binder} via the exposed methods. */ protected abstract void configure(); /** * Gets direct access to the underlying {@code Binder}. */ protected Binder binder() { return binder; } /** * @see Binder#bindScope(Class, Scope) */ protected void bindScope(Class scopeAnnotation, Scope scope) { binder.bindScope(scopeAnnotation, scope); } /** * @see Binder#bind(Key) */ protected LinkedBindingBuilder bind(Key key) { return binder.bind(key); } /** * @see Binder#bind(TypeLiteral) */ protected AnnotatedBindingBuilder bind(TypeLiteral typeLiteral) { return binder.bind(typeLiteral); } /** * @see Binder#bind(Class) */ protected AnnotatedBindingBuilder bind(Class clazz) { return binder.bind(clazz); } /** * @see Binder#bindConstant() */ protected AnnotatedConstantBindingBuilder bindConstant() { return binder.bindConstant(); } /** * @see Binder#install(Module) */ protected void install(Module module) { binder.install(module); } /** * @see Binder#addError(String, Object[]) */ protected void addError(String message, Object... arguments) { binder.addError(message, arguments); } /** * @see Binder#addError(Throwable) */ protected void addError(Throwable t) { binder.addError(t); } /** * @see Binder#addError(Message) * @since 2.0 */ protected void addError(Message message) { binder.addError(message); } /** * @see Binder#requestInjection(Object) * @since 2.0 */ protected void requestInjection(Object instance) { binder.requestInjection(instance); } /** * @see Binder#requestStaticInjection(Class[]) */ protected void requestStaticInjection(Class... types) { binder.requestStaticInjection(types); } /*if[AOP]*/ /** * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher, * com.google.inject.matcher.Matcher, * org.aopalliance.intercept.MethodInterceptor[]) */ protected void bindInterceptor(Matcher> classMatcher, Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors) { binder.bindInterceptor(classMatcher, methodMatcher, interceptors); } /*end[AOP]*/ /** * Adds a dependency from this module to {@code key}. When the injector is * created, Guice will report an error if {@code key} cannot be injected. * Note that this requirement may be satisfied by implicit binding, such as * a public no-arguments constructor. * * @since 2.0 */ protected void requireBinding(Key key) { binder.getProvider(key); } /** * Adds a dependency from this module to {@code type}. When the injector is * created, Guice will report an error if {@code type} cannot be injected. * Note that this requirement may be satisfied by implicit binding, such as * a public no-arguments constructor. * * @since 2.0 */ protected void requireBinding(Class type) { binder.getProvider(type); } /** * @see Binder#getProvider(Key) * @since 2.0 */ protected Provider getProvider(Key key) { return binder.getProvider(key); } /** * @see Binder#getProvider(Class) * @since 2.0 */ protected Provider getProvider(Class type) { return binder.getProvider(type); } /** * @see Binder#convertToTypes * @since 2.0 */ protected void convertToTypes(Matcher> typeMatcher, TypeConverter converter) { binder.convertToTypes(typeMatcher, converter); } /** * @see Binder#currentStage() * @since 2.0 */ protected Stage currentStage() { return binder.currentStage(); } /** * @see Binder#getMembersInjector(Class) * @since 2.0 */ protected MembersInjector getMembersInjector(Class type) { return binder.getMembersInjector(type); } /** * @see Binder#getMembersInjector(TypeLiteral) * @since 2.0 */ protected MembersInjector getMembersInjector(TypeLiteral type) { return binder.getMembersInjector(type); } /** * @see Binder#bindListener(com.google.inject.matcher.Matcher, * com.google.inject.spi.TypeListener) * @since 2.0 */ protected void bindListener(Matcher> typeMatcher, TypeListener listener) { binder.bindListener(typeMatcher, listener); } } guice-3.0/core/src/com/google/inject/Provider.java0000644000175000017500000000453611460133000022022 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; /** * An object capable of providing instances of type {@code T}. Providers are used in numerous ways * by Guice: * *
    *
  • When the default means for obtaining instances (an injectable or parameterless constructor) * is insufficient for a particular binding, the module can specify a custom {@code Provider} * instead, to control exactly how Guice creates or obtains instances for the binding. * *
  • An implementation class may always choose to have a {@code Provider} instance injected, * rather than having a {@code T} injected directly. This may give you access to multiple * instances, instances you wish to safely mutate and discard, instances which are out of scope * (e.g. using a {@code @RequestScoped} object from within a {@code @SessionScoped} object), or * instances that will be initialized lazily. * *
  • A custom {@link Scope} is implemented as a decorator of {@code Provider}, which decides * when to delegate to the backing provider and when to provide the instance some other way. * *
  • The {@link Injector} offers access to the {@code Provider} it uses to fulfill requests * for a given key, via the {@link Injector#getProvider} methods. *
* * @param the type of object this provides * * @author crazybob@google.com (Bob Lee) */ public interface Provider extends javax.inject.Provider { /** * Provides an instance of {@code T}. Must never return {@code null}. * * @throws OutOfScopeException when an attempt is made to access a scoped object while the scope * in question is not currently active * @throws ProvisionException if an instance cannot be provided. Such exceptions include messages * and throwables to describe why provision failed. */ T get(); } guice-3.0/core/src/com/google/inject/internal/0000755000175000017500000000000011536227706021216 5ustar drazzibdrazzibguice-3.0/core/src/com/google/inject/internal/Initializables.java0000644000175000017500000000211311460133000024774 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; /** * @author jessewilson@google.com (Jesse Wilson) */ final class Initializables { /** * Returns an initializable for an instance that requires no initialization. */ static Initializable of(final T instance) { return new Initializable() { public T get(Errors errors) throws ErrorsException { return instance; } @Override public String toString() { return String.valueOf(instance); } }; } } guice-3.0/core/src/com/google/inject/internal/TypeListenerBindingProcessor.java0000644000175000017500000000205311460133000027656 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.spi.TypeListenerBinding; /** * Handles {@code Binder#bindListener} commands. * * @author jessewilson@google.com (Jesse Wilson) */ final class TypeListenerBindingProcessor extends AbstractProcessor { TypeListenerBindingProcessor(Errors errors) { super(errors); } @Override public Boolean visit(TypeListenerBinding binding) { injector.state.addTypeListener(binding); return true; } }guice-3.0/core/src/com/google/inject/internal/UntargettedBindingImpl.java0000644000175000017500000000510711460133000026442 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.internal.util.Objects; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.UntargettedBinding; final class UntargettedBindingImpl extends BindingImpl implements UntargettedBinding { UntargettedBindingImpl(InjectorImpl injector, Key key, Object source) { super(injector, key, source, new InternalFactory() { public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) { throw new AssertionError(); } }, Scoping.UNSCOPED); } public UntargettedBindingImpl(Object source, Key key, Scoping scoping) { super(source, key, scoping); } public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } public BindingImpl withScoping(Scoping scoping) { return new UntargettedBindingImpl(getSource(), getKey(), scoping); } public BindingImpl withKey(Key key) { return new UntargettedBindingImpl(getSource(), key, getScoping()); } public void applyTo(Binder binder) { getScoping().applyTo(binder.withSource(getSource()).bind(getKey())); } @Override public String toString() { return new ToStringBuilder(UntargettedBinding.class) .add("key", getKey()) .add("source", getSource()) .toString(); } @Override public boolean equals(Object obj) { if(obj instanceof UntargettedBindingImpl) { UntargettedBindingImpl o = (UntargettedBindingImpl)obj; return getKey().equals(o.getKey()) && getScoping().equals(o.getScoping()); } else { return false; } } @Override public int hashCode() { return Objects.hashCode(getKey(), getScoping()); } } guice-3.0/core/src/com/google/inject/internal/State.java0000644000175000017500000001264011532155102023126 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.Scope; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.spi.TypeConverterBinding; import com.google.inject.spi.TypeListenerBinding; import java.lang.annotation.Annotation; import java.util.List; import java.util.Map; import java.util.Set; /** * The inheritable data within an injector. This class is intended to allow parent and local * injector data to be accessed as a unit. * * @author jessewilson@google.com (Jesse Wilson) */ interface State { static final State NONE = new State() { public State parent() { throw new UnsupportedOperationException(); } public BindingImpl getExplicitBinding(Key key) { return null; } public Map, Binding> getExplicitBindingsThisLevel() { throw new UnsupportedOperationException(); } public void putBinding(Key key, BindingImpl binding) { throw new UnsupportedOperationException(); } public Scope getScope(Class scopingAnnotation) { return null; } public void putAnnotation(Class annotationType, Scope scope) { throw new UnsupportedOperationException(); } public void addConverter(TypeConverterBinding typeConverterBinding) { throw new UnsupportedOperationException(); } public TypeConverterBinding getConverter(String stringValue, TypeLiteral type, Errors errors, Object source) { throw new UnsupportedOperationException(); } public Iterable getConvertersThisLevel() { return ImmutableSet.of(); } /*if[AOP]*/ public void addMethodAspect(MethodAspect methodAspect) { throw new UnsupportedOperationException(); } public ImmutableList getMethodAspects() { return ImmutableList.of(); } /*end[AOP]*/ public void addTypeListener(TypeListenerBinding typeListenerBinding) { throw new UnsupportedOperationException(); } public List getTypeListenerBindings() { return ImmutableList.of(); } public void blacklist(Key key, Object source) { } public boolean isBlacklisted(Key key) { return true; } public Set getSourcesForBlacklistedKey(Key key) { throw new UnsupportedOperationException(); } public Object lock() { throw new UnsupportedOperationException(); } public Map, Scope> getScopes() { return ImmutableMap.of(); } }; State parent(); /** Gets a binding which was specified explicitly in a module, or null. */ BindingImpl getExplicitBinding(Key key); /** Returns the explicit bindings at this level only. */ Map, Binding> getExplicitBindingsThisLevel(); void putBinding(Key key, BindingImpl binding); /** Returns the matching scope, or null. */ Scope getScope(Class scopingAnnotation); void putAnnotation(Class annotationType, Scope scope); void addConverter(TypeConverterBinding typeConverterBinding); /** Returns the matching converter for {@code type}, or null if none match. */ TypeConverterBinding getConverter( String stringValue, TypeLiteral type, Errors errors, Object source); /** Returns all converters at this level only. */ Iterable getConvertersThisLevel(); /*if[AOP]*/ void addMethodAspect(MethodAspect methodAspect); ImmutableList getMethodAspects(); /*end[AOP]*/ void addTypeListener(TypeListenerBinding typeListenerBinding); List getTypeListenerBindings(); /** * Forbids the corresponding injector from creating a binding to {@code key}. Child injectors * blacklist their bound keys on their parent injectors to prevent just-in-time bindings on the * parent injector that would conflict. */ void blacklist(Key key, Object source); /** * Returns true if {@code key} is forbidden from being bound in this injector. This indicates that * one of this injector's descendent's has bound the key. */ boolean isBlacklisted(Key key); /** Returns the source of a blacklisted key. */ Set getSourcesForBlacklistedKey(Key key); /** * Returns the shared lock for all injector data. This is a low-granularity, high-contention lock * to be used when reading mutable data (ie. just-in-time bindings, and binding blacklists). */ Object lock(); /** * Returns all the scope bindings at this level and parent levels. */ Map, Scope> getScopes(); } guice-3.0/core/src/com/google/inject/internal/ContextualCallable.java0000644000175000017500000000141111460133000025577 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; /** * @author crazybob@google.com (Bob Lee) */ interface ContextualCallable { T call(InternalContext context) throws ErrorsException; } guice-3.0/core/src/com/google/inject/internal/BoundProviderFactory.java0000644000175000017500000000424711536227366026204 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Key; import com.google.inject.internal.InjectorImpl.JitLimitation; import com.google.inject.spi.Dependency; /** * Delegates to a custom factory which is also bound in the injector. */ final class BoundProviderFactory implements InternalFactory, CreationListener { private final InjectorImpl injector; final Key> providerKey; final Object source; private InternalFactory> providerFactory; BoundProviderFactory( InjectorImpl injector, Key> providerKey, Object source) { this.injector = injector; this.providerKey = providerKey; this.source = source; } public void notify(Errors errors) { try { providerFactory = injector.getInternalFactory(providerKey, errors.withSource(source), JitLimitation.NEW_OR_EXISTING_JIT); } catch (ErrorsException e) { errors.merge(e.getErrors()); } } public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) throws ErrorsException { errors = errors.withSource(providerKey); javax.inject.Provider provider = providerFactory.get(errors, context, dependency, true); try { return errors.checkForNull(provider.get(), source, dependency); } catch(RuntimeException userException) { throw errors.errorInProvider(userException).toException(); } } @Override public String toString() { return providerKey.toString(); } } guice-3.0/core/src/com/google/inject/internal/EncounterImpl.java0000644000175000017500000001077411460133000024631 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Key; import com.google.inject.MembersInjector; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Lists; import static com.google.inject.internal.util.Preconditions.checkState; import com.google.inject.matcher.Matcher; import com.google.inject.matcher.Matchers; import com.google.inject.spi.InjectionListener; import com.google.inject.spi.Message; import com.google.inject.spi.TypeEncounter; import java.lang.reflect.Method; import java.util.List; /** * @author jessewilson@google.com (Jesse Wilson) */ final class EncounterImpl implements TypeEncounter { private final Errors errors; private final Lookups lookups; private List> membersInjectors; // lazy private List> injectionListeners; // lazy /*if[AOP]*/ private List aspects; // lazy /*end[AOP]*/ private boolean valid = true; EncounterImpl(Errors errors, Lookups lookups) { this.errors = errors; this.lookups = lookups; } void invalidate() { valid = false; } /*if[AOP]*/ ImmutableList getAspects() { return aspects == null ? ImmutableList.of() : ImmutableList.copyOf(aspects); } public void bindInterceptor(Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors) { checkState(valid, "Encounters may not be used after hear() returns."); // make sure the applicable aspects is mutable if (aspects == null) { aspects = Lists.newArrayList(); } aspects.add(new MethodAspect(Matchers.any(), methodMatcher, interceptors)); } /*end[AOP]*/ ImmutableList> getMembersInjectors() { return membersInjectors == null ? ImmutableList.>of() : ImmutableList.copyOf(membersInjectors); } ImmutableList> getInjectionListeners() { return injectionListeners == null ? ImmutableList.>of() : ImmutableList.copyOf(injectionListeners); } public void register(MembersInjector membersInjector) { checkState(valid, "Encounters may not be used after hear() returns."); if (membersInjectors == null) { membersInjectors = Lists.newArrayList(); } membersInjectors.add(membersInjector); } public void register(InjectionListener injectionListener) { checkState(valid, "Encounters may not be used after hear() returns."); if (injectionListeners == null) { injectionListeners = Lists.newArrayList(); } injectionListeners.add(injectionListener); } public void addError(String message, Object... arguments) { checkState(valid, "Encounters may not be used after hear() returns."); errors.addMessage(message, arguments); } public void addError(Throwable t) { checkState(valid, "Encounters may not be used after hear() returns."); errors.errorInUserCode(t, "An exception was caught and reported. Message: %s", t.getMessage()); } public void addError(Message message) { checkState(valid, "Encounters may not be used after hear() returns."); errors.addMessage(message); } public Provider getProvider(Key key) { checkState(valid, "Encounters may not be used after hear() returns."); return lookups.getProvider(key); } public Provider getProvider(Class type) { return getProvider(Key.get(type)); } public MembersInjector getMembersInjector(TypeLiteral typeLiteral) { checkState(valid, "Encounters may not be used after hear() returns."); return lookups.getMembersInjector(typeLiteral); } public MembersInjector getMembersInjector(Class type) { return getMembersInjector(TypeLiteral.get(type)); } }guice-3.0/core/src/com/google/inject/internal/package-info.java0000644000175000017500000000125311460133000024361 0ustar drazzibdrazzib/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Guice (sounds like like "juice") */ package com.google.inject.internal;guice-3.0/core/src/com/google/inject/internal/InternalFactoryToProviderAdapter.java0000644000175000017500000000324611460133000030464 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Provider; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.spi.Dependency; /** * @author crazybob@google.com (Bob Lee) */ final class InternalFactoryToProviderAdapter implements InternalFactory { private final Initializable> initializable; private final Object source; public InternalFactoryToProviderAdapter( Initializable> initializable, Object source) { this.initializable = checkNotNull(initializable, "provider"); this.source = checkNotNull(source, "source"); } public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) throws ErrorsException { try { return errors.checkForNull(initializable.get(errors).get(), source, dependency); } catch (RuntimeException userException) { throw errors.withSource(source).errorInProvider(userException).toException(); } } @Override public String toString() { return initializable.toString(); } } guice-3.0/core/src/com/google/inject/internal/Scoping.java0000644000175000017500000001677011460133000023451 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.Scopes; import com.google.inject.Singleton; import com.google.inject.Stage; import com.google.inject.binder.ScopedBindingBuilder; import com.google.inject.internal.util.Objects; import com.google.inject.spi.BindingScopingVisitor; import java.lang.annotation.Annotation; /** * References a scope, either directly (as a scope instance), or indirectly (as a scope annotation). * The scope's eager or laziness is also exposed. * * @author jessewilson@google.com (Jesse Wilson) */ public abstract class Scoping { /** * No scoping annotation has been applied. Note that this is different from {@code * in(Scopes.NO_SCOPE)}, where the 'NO_SCOPE' has been explicitly applied. */ public static final Scoping UNSCOPED = new Scoping() { public V acceptVisitor(BindingScopingVisitor visitor) { return visitor.visitNoScoping(); } @Override public Scope getScopeInstance() { return Scopes.NO_SCOPE; } @Override public String toString() { return Scopes.NO_SCOPE.toString(); } public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { // do nothing } }; public static final Scoping SINGLETON_ANNOTATION = new Scoping() { public V acceptVisitor(BindingScopingVisitor visitor) { return visitor.visitScopeAnnotation(Singleton.class); } @Override public Class getScopeAnnotation() { return Singleton.class; } @Override public String toString() { return Singleton.class.getName(); } public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { scopedBindingBuilder.in(Singleton.class); } }; public static final Scoping SINGLETON_INSTANCE = new Scoping() { public V acceptVisitor(BindingScopingVisitor visitor) { return visitor.visitScope(Scopes.SINGLETON); } @Override public Scope getScopeInstance() { return Scopes.SINGLETON; } @Override public String toString() { return Scopes.SINGLETON.toString(); } public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { scopedBindingBuilder.in(Scopes.SINGLETON); } }; public static final Scoping EAGER_SINGLETON = new Scoping() { public V acceptVisitor(BindingScopingVisitor visitor) { return visitor.visitEagerSingleton(); } @Override public Scope getScopeInstance() { return Scopes.SINGLETON; } @Override public String toString() { return "eager singleton"; } public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { scopedBindingBuilder.asEagerSingleton(); } }; public static Scoping forAnnotation(final Class scopingAnnotation) { if (scopingAnnotation == Singleton.class || scopingAnnotation == javax.inject.Singleton.class) { return SINGLETON_ANNOTATION; } return new Scoping() { public V acceptVisitor(BindingScopingVisitor visitor) { return visitor.visitScopeAnnotation(scopingAnnotation); } @Override public Class getScopeAnnotation() { return scopingAnnotation; } @Override public String toString() { return scopingAnnotation.getName(); } public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { scopedBindingBuilder.in(scopingAnnotation); } }; } public static Scoping forInstance(final Scope scope) { if (scope == Scopes.SINGLETON) { return SINGLETON_INSTANCE; } return new Scoping() { public V acceptVisitor(BindingScopingVisitor visitor) { return visitor.visitScope(scope); } @Override public Scope getScopeInstance() { return scope; } @Override public String toString() { return scope.toString(); } public void applyTo(ScopedBindingBuilder scopedBindingBuilder) { scopedBindingBuilder.in(scope); } }; } /** * Returns true if this scope was explicitly applied. If no scope was explicitly applied then the * scoping annotation will be used. */ public boolean isExplicitlyScoped() { return this != UNSCOPED; } /** * Returns true if this is the default scope. In this case a new instance will be provided for * each injection. */ public boolean isNoScope() { return getScopeInstance() == Scopes.NO_SCOPE; } /** * Returns true if this scope is a singleton that should be loaded eagerly in {@code stage}. */ public boolean isEagerSingleton(Stage stage) { if (this == EAGER_SINGLETON) { return true; } if (stage == Stage.PRODUCTION) { return this == SINGLETON_ANNOTATION || this == SINGLETON_INSTANCE; } return false; } /** * Returns the scope instance, or {@code null} if that isn't known for this instance. */ public Scope getScopeInstance() { return null; } /** * Returns the scope annotation, or {@code null} if that isn't known for this instance. */ public Class getScopeAnnotation() { return null; } @Override public boolean equals(Object obj) { if(obj instanceof Scoping) { Scoping o = (Scoping)obj; return Objects.equal(getScopeAnnotation(), o.getScopeAnnotation()) && Objects.equal(getScopeInstance(), o.getScopeInstance()); } else { return false; } } @Override public int hashCode() { return Objects.hashCode(getScopeAnnotation(), getScopeInstance()); } public abstract V acceptVisitor(BindingScopingVisitor visitor); public abstract void applyTo(ScopedBindingBuilder scopedBindingBuilder); private Scoping() {} /** Scopes an internal factory. */ static InternalFactory scope(Key key, InjectorImpl injector, InternalFactory creator, Object source, Scoping scoping) { if (scoping.isNoScope()) { return creator; } Scope scope = scoping.getScopeInstance(); Provider scoped = scope.scope(key, new ProviderToInternalFactoryAdapter(injector, creator)); return new InternalFactoryToProviderAdapter( Initializables.>of(scoped), source); } /** * Replaces annotation scopes with instance scopes using the Injector's annotation-to-instance * map. If the scope annotation has no corresponding instance, an error will be added and unscoped * will be retuned. */ static Scoping makeInjectable(Scoping scoping, InjectorImpl injector, Errors errors) { Class scopeAnnotation = scoping.getScopeAnnotation(); if (scopeAnnotation == null) { return scoping; } Scope scope = injector.state.getScope(scopeAnnotation); if (scope != null) { return forInstance(scope); } errors.scopeNotFound(scopeAnnotation); return UNSCOPED; } } guice-3.0/core/src/com/google/inject/internal/Nullability.java0000644000175000017500000000236311462357750024356 0ustar drazzibdrazzibpackage com.google.inject.internal; import java.lang.annotation.Annotation; import com.google.inject.internal.util.Nullable; /** * Whether a member supports null values injected. * *

Support for {@code Nullable} annotations in Guice is loose. * Any annotation type whose simplename is "Nullable" is sufficient to indicate * support for null values injected. * *

This allows support for JSR-305's * * javax.annotation.meta.Nullable annotation and IntelliJ IDEA's * * org.jetbrains.annotations.Nullable. * * @author jessewilson@google.com (Jesse Wilson) */ public class Nullability { private Nullability() {} public static boolean allowsNull(Annotation[] annotations) { for(Annotation a : annotations) { Class type = a.annotationType(); // Check for Nullable.class because our c.g.i.internal.util.Nullable // gets jarjar'd into $Nullable, and we want extensions that reference // it to continue working. if ("Nullable".equals(type.getSimpleName()) || type == Nullable.class) { return true; } } return false; } } guice-3.0/core/src/com/google/inject/internal/SingleFieldInjector.java0000644000175000017500000000413111460133000025716 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.InjectorImpl.JitLimitation; import com.google.inject.spi.Dependency; import com.google.inject.spi.InjectionPoint; import java.lang.reflect.Field; /** * Sets an injectable field. */ final class SingleFieldInjector implements SingleMemberInjector { final Field field; final InjectionPoint injectionPoint; final Dependency dependency; final InternalFactory factory; public SingleFieldInjector(InjectorImpl injector, InjectionPoint injectionPoint, Errors errors) throws ErrorsException { this.injectionPoint = injectionPoint; this.field = (Field) injectionPoint.getMember(); this.dependency = injectionPoint.getDependencies().get(0); // Ewwwww... field.setAccessible(true); factory = injector.getInternalFactory(dependency.getKey(), errors, JitLimitation.NO_JIT); } public InjectionPoint getInjectionPoint() { return injectionPoint; } public void inject(Errors errors, InternalContext context, Object o) { errors = errors.withSource(dependency); Dependency previous = context.setDependency(dependency); try { Object value = factory.get(errors, context, dependency, false); field.set(o, value); } catch (ErrorsException e) { errors.withSource(injectionPoint).merge(e.getErrors()); } catch (IllegalAccessException e) { throw new AssertionError(e); // a security manager is blocking us, we're hosed } finally { context.setDependency(previous); } } } guice-3.0/core/src/com/google/inject/internal/ProcessedBindingData.java0000644000175000017500000000311311536227264026072 0ustar drazzibdrazzib/** * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import java.util.List; import com.google.inject.internal.util.Lists; /** * Keeps track of creation listeners & uninitialized bindings, * so they can be processed after bindings are recorded. * * @author sameb@google.com (Sam Berlin) */ class ProcessedBindingData { private final List creationListeners = Lists.newArrayList(); private final List uninitializedBindings = Lists.newArrayList(); void addCreationListener(CreationListener listener) { creationListeners.add(listener); } void addUninitializedBinding(Runnable runnable) { uninitializedBindings.add(runnable); } void initializeBindings() { for (Runnable initializer : uninitializedBindings) { initializer.run(); } } void runCreationListeners(Errors errors) { for (CreationListener creationListener : creationListeners) { creationListener.notify(errors); } } } guice-3.0/core/src/com/google/inject/internal/InternalFactory.java0000644000175000017500000000227111460133000025142 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.spi.Dependency; /** * Creates objects which will be injected. * * @author crazybob@google.com (Bob Lee) */ interface InternalFactory { /** * Creates an object to be injected. * @param context of this injection * @param linked true if getting as a result of a linked binding * * @throws com.google.inject.internal.ErrorsException if a value cannot be provided * @return instance to be injected */ T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) throws ErrorsException; } guice-3.0/core/src/com/google/inject/internal/MembersInjectorStore.java0000644000175000017500000001160611530444542026163 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.ConfigurationException; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Lists; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.TypeListenerBinding; import java.lang.reflect.Field; import java.util.List; import java.util.Set; /** * Members injectors by type. * * @author jessewilson@google.com (Jesse Wilson) */ final class MembersInjectorStore { private final InjectorImpl injector; private final ImmutableList typeListenerBindings; private final FailableCache, MembersInjectorImpl> cache = new FailableCache, MembersInjectorImpl>() { @Override protected MembersInjectorImpl create(TypeLiteral type, Errors errors) throws ErrorsException { return createWithListeners(type, errors); } }; MembersInjectorStore(InjectorImpl injector, List typeListenerBindings) { this.injector = injector; this.typeListenerBindings = ImmutableList.copyOf(typeListenerBindings); } /** * Returns true if any type listeners are installed. Other code may take shortcuts when there * aren't any type listeners. */ public boolean hasTypeListeners() { return !typeListenerBindings.isEmpty(); } /** * Returns a new complete members injector with injection listeners registered. */ @SuppressWarnings("unchecked") // the MembersInjector type always agrees with the passed type public MembersInjectorImpl get(TypeLiteral key, Errors errors) throws ErrorsException { return (MembersInjectorImpl) cache.get(key, errors); } /** * Purges a type literal from the cache. Use this only if the type is not actually valid for * binding and needs to be purged. (See issue 319 and * ImplicitBindingTest#testCircularJitBindingsLeaveNoResidue and * #testInstancesRequestingProvidersForThemselvesWithChildInjectors for examples of when this is * necessary.) * * Returns true if the type was stored in the cache, false otherwise. */ boolean remove(TypeLiteral type) { return cache.remove(type); } /** * Creates a new members injector and attaches both injection listeners and method aspects. */ private MembersInjectorImpl createWithListeners(TypeLiteral type, Errors errors) throws ErrorsException { int numErrorsBefore = errors.size(); Set injectionPoints; try { injectionPoints = InjectionPoint.forInstanceMethodsAndFields(type); } catch (ConfigurationException e) { errors.merge(e.getErrorMessages()); injectionPoints = e.getPartialValue(); } ImmutableList injectors = getInjectors(injectionPoints, errors); errors.throwIfNewErrors(numErrorsBefore); EncounterImpl encounter = new EncounterImpl(errors, injector.lookups); for (TypeListenerBinding typeListener : typeListenerBindings) { if (typeListener.getTypeMatcher().matches(type)) { try { typeListener.getListener().hear(type, encounter); } catch (RuntimeException e) { errors.errorNotifyingTypeListener(typeListener, type, e); } } } encounter.invalidate(); errors.throwIfNewErrors(numErrorsBefore); return new MembersInjectorImpl(injector, type, encounter, injectors); } /** * Returns the injectors for the specified injection points. */ ImmutableList getInjectors( Set injectionPoints, Errors errors) { List injectors = Lists.newArrayList(); for (InjectionPoint injectionPoint : injectionPoints) { try { Errors errorsForMember = injectionPoint.isOptional() ? new Errors(injectionPoint) : errors.withSource(injectionPoint); SingleMemberInjector injector = injectionPoint.getMember() instanceof Field ? new SingleFieldInjector(this.injector, injectionPoint, errorsForMember) : new SingleMethodInjector(this.injector, injectionPoint, errorsForMember); injectors.add(injector); } catch (ErrorsException ignoredForNow) { // ignored for now } } return ImmutableList.copyOf(injectors); } } guice-3.0/core/src/com/google/inject/internal/MembersInjectorImpl.java0000644000175000017500000001216011460133000025746 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.MembersInjector; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.spi.InjectionListener; import com.google.inject.spi.InjectionPoint; /** * Injects members of instances of a given type. * * @author jessewilson@google.com (Jesse Wilson) */ final class MembersInjectorImpl implements MembersInjector { private final TypeLiteral typeLiteral; private final InjectorImpl injector; private final ImmutableList memberInjectors; private final ImmutableList> userMembersInjectors; private final ImmutableList> injectionListeners; /*if[AOP]*/ private final ImmutableList addedAspects; /*end[AOP]*/ MembersInjectorImpl(InjectorImpl injector, TypeLiteral typeLiteral, EncounterImpl encounter, ImmutableList memberInjectors) { this.injector = injector; this.typeLiteral = typeLiteral; this.memberInjectors = memberInjectors; this.userMembersInjectors = encounter.getMembersInjectors(); this.injectionListeners = encounter.getInjectionListeners(); /*if[AOP]*/ this.addedAspects = encounter.getAspects(); /*end[AOP]*/ } public ImmutableList getMemberInjectors() { return memberInjectors; } public void injectMembers(T instance) { Errors errors = new Errors(typeLiteral); try { injectAndNotify(instance, errors, false); } catch (ErrorsException e) { errors.merge(e.getErrors()); } errors.throwProvisionExceptionIfErrorsExist(); } void injectAndNotify(final T instance, final Errors errors, final boolean toolableOnly) throws ErrorsException { if (instance == null) { return; } injector.callInContext(new ContextualCallable() { public Void call(InternalContext context) throws ErrorsException { injectMembers(instance, errors, context, toolableOnly); return null; } }); // TODO: We *could* notify listeners too here, // but it's not clear if we want to. There's no way to know // if a MembersInjector from the usersMemberInjector list wants // toolable injections, so do we really want to notify // about injection? (We could take a strategy of only notifying // if atleast one InjectionPoint was toolable, in which case // the above callInContext could return 'true' if it injected // anything.) if(!toolableOnly) { notifyListeners(instance, errors); } } void notifyListeners(T instance, Errors errors) throws ErrorsException { int numErrorsBefore = errors.size(); for (InjectionListener injectionListener : injectionListeners) { try { injectionListener.afterInjection(instance); } catch (RuntimeException e) { errors.errorNotifyingInjectionListener(injectionListener, typeLiteral, e); } } errors.throwIfNewErrors(numErrorsBefore); } void injectMembers(T t, Errors errors, InternalContext context, boolean toolableOnly) { // optimization: use manual for/each to save allocating an iterator here for (int i = 0, size = memberInjectors.size(); i < size; i++) { SingleMemberInjector injector = memberInjectors.get(i); if(!toolableOnly || injector.getInjectionPoint().isToolable()) { injector.inject(errors, context, t); } } // TODO: There's no way to know if a user's MembersInjector wants toolable injections. if(!toolableOnly) { // optimization: use manual for/each to save allocating an iterator here for (int i = 0, size = userMembersInjectors.size(); i < size; i++) { MembersInjector userMembersInjector = userMembersInjectors.get(i); try { userMembersInjector.injectMembers(t); } catch (RuntimeException e) { errors.errorInUserInjector(userMembersInjector, typeLiteral, e); } } } } @Override public String toString() { return "MembersInjector<" + typeLiteral + ">"; } public ImmutableSet getInjectionPoints() { ImmutableSet.Builder builder = ImmutableSet.builder(); for (SingleMemberInjector memberInjector : memberInjectors) { builder.add(memberInjector.getInjectionPoint()); } return builder.build(); } /*if[AOP]*/ public ImmutableList getAddedAspects() { return addedAspects; } /*end[AOP]*/ } guice-3.0/core/src/com/google/inject/internal/InterceptorStackCallback.java0000644000175000017500000000710611532662510026756 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.util.Lists; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import net.sf.cglib.proxy.MethodProxy; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * Intercepts a method with a stack of interceptors. * * @author crazybob@google.com (Bob Lee) */ final class InterceptorStackCallback implements net.sf.cglib.proxy.MethodInterceptor { private static final Set AOP_INTERNAL_CLASSES = new HashSet(Arrays.asList( InterceptorStackCallback.class.getName(), InterceptedMethodInvocation.class.getName(), MethodProxy.class.getName())); final MethodInterceptor[] interceptors; final Method method; public InterceptorStackCallback(Method method, List interceptors) { this.method = method; this.interceptors = interceptors.toArray(new MethodInterceptor[interceptors.size()]); } public Object intercept(Object proxy, Method method, Object[] arguments, MethodProxy methodProxy) throws Throwable { return new InterceptedMethodInvocation(proxy, methodProxy, arguments).proceed(); } private class InterceptedMethodInvocation implements MethodInvocation { final Object proxy; final Object[] arguments; final MethodProxy methodProxy; int index = -1; public InterceptedMethodInvocation(Object proxy, MethodProxy methodProxy, Object[] arguments) { this.proxy = proxy; this.methodProxy = methodProxy; this.arguments = arguments; } public Object proceed() throws Throwable { try { index++; return index == interceptors.length ? methodProxy.invokeSuper(proxy, arguments) : interceptors[index].invoke(this); } catch (Throwable t) { pruneStacktrace(t); throw t; } finally { index--; } } public Method getMethod() { return method; } public Object[] getArguments() { return arguments; } public Object getThis() { return proxy; } public AccessibleObject getStaticPart() { return getMethod(); } } /** * Removes stacktrace elements related to AOP internal mechanics from the * throwable's stack trace and any causes it may have. */ private void pruneStacktrace(Throwable throwable) { for(Throwable t = throwable; t != null; t = t.getCause()) { StackTraceElement[] stackTrace = t.getStackTrace(); List pruned = Lists.newArrayList(); for (StackTraceElement element : stackTrace) { String className = element.getClassName(); if (!AOP_INTERNAL_CLASSES.contains(className) && !className.contains("$EnhancerByGuice$")) { pruned.add(element); } } t.setStackTrace(pruned.toArray(new StackTraceElement[pruned.size()])); } } } guice-3.0/core/src/com/google/inject/internal/ProxyFactory.java0000644000175000017500000002341211530232552024521 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import static com.google.inject.internal.BytecodeGen.newFastClass; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Maps; import com.google.inject.spi.InjectionPoint; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.CallbackFilter; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.reflect.FastClass; import net.sf.cglib.reflect.FastConstructor; import org.aopalliance.intercept.MethodInterceptor; /** * Builds a construction proxy that can participate in AOP. This class manages applying type and * method matchers to come up with the set of intercepted methods. * * @author jessewilson@google.com (Jesse Wilson) */ final class ProxyFactory implements ConstructionProxyFactory { private static final Logger logger = Logger.getLogger(ProxyFactory.class.getName()); private final InjectionPoint injectionPoint; private final ImmutableMap> interceptors; private final Class declaringClass; private final List methods; private final Callback[] callbacks; /** * PUBLIC is default; it's used if all the methods we're intercepting are public. This impacts * which classloader we should use for loading the enhanced class */ private BytecodeGen.Visibility visibility = BytecodeGen.Visibility.PUBLIC; ProxyFactory(InjectionPoint injectionPoint, Iterable methodAspects) { this.injectionPoint = injectionPoint; @SuppressWarnings("unchecked") // the member of injectionPoint is always a Constructor Constructor constructor = (Constructor) injectionPoint.getMember(); declaringClass = constructor.getDeclaringClass(); // Find applicable aspects. Bow out if none are applicable to this class. List applicableAspects = Lists.newArrayList(); for (MethodAspect methodAspect : methodAspects) { if (methodAspect.matches(declaringClass)) { applicableAspects.add(methodAspect); } } if (applicableAspects.isEmpty()) { interceptors = ImmutableMap.of(); methods = ImmutableList.of(); callbacks = null; return; } // Get list of methods from cglib. methods = Lists.newArrayList(); Enhancer.getMethods(declaringClass, null, methods); // Create method/interceptor holders and record indices. List methodInterceptorsPairs = Lists.newArrayList(); for (Method method : methods) { methodInterceptorsPairs.add(new MethodInterceptorsPair(method)); } // Iterate over aspects and add interceptors for the methods they apply to boolean anyMatched = false; for (MethodAspect methodAspect : applicableAspects) { for (MethodInterceptorsPair pair : methodInterceptorsPairs) { if (methodAspect.matches(pair.method)) { if(pair.method.isSynthetic()) { logger.log(Level.WARNING, "Method [{0}] is synthetic and is being intercepted by {1}." + " This could indicate a bug. The method may be intercepted twice," + " or may not be intercepted at all.", new Object[] { pair.method, methodAspect.interceptors() }); } visibility = visibility.and(BytecodeGen.Visibility.forMember(pair.method)); pair.addAll(methodAspect.interceptors()); anyMatched = true; } } } if (!anyMatched) { interceptors = ImmutableMap.of(); callbacks = null; return; } ImmutableMap.Builder> interceptorsMapBuilder = null; // lazy callbacks = new Callback[methods.size()]; for (int i = 0; i < methods.size(); i++) { MethodInterceptorsPair pair = methodInterceptorsPairs.get(i); if (!pair.hasInterceptors()) { callbacks[i] = net.sf.cglib.proxy.NoOp.INSTANCE; continue; } if (interceptorsMapBuilder == null) { interceptorsMapBuilder = ImmutableMap.builder(); } interceptorsMapBuilder.put(pair.method, ImmutableList.copyOf(pair.interceptors)); callbacks[i] = new InterceptorStackCallback(pair.method, pair.interceptors); } interceptors = interceptorsMapBuilder != null ? interceptorsMapBuilder.build() : ImmutableMap.>of(); } /** * Returns the interceptors that apply to the constructed type. */ public ImmutableMap> getInterceptors() { return interceptors; } public ConstructionProxy create() throws ErrorsException { if (interceptors.isEmpty()) { return new DefaultConstructionProxyFactory(injectionPoint).create(); } @SuppressWarnings("unchecked") Class[] callbackTypes = new Class[callbacks.length]; for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] == net.sf.cglib.proxy.NoOp.INSTANCE) { callbackTypes[i] = net.sf.cglib.proxy.NoOp.class; } else { callbackTypes[i] = net.sf.cglib.proxy.MethodInterceptor.class; } } // Create the proxied class. We're careful to ensure that all enhancer state is not-specific // to this injector. Otherwise, the proxies for each injector will waste PermGen memory try { Enhancer enhancer = BytecodeGen.newEnhancer(declaringClass, visibility); enhancer.setCallbackFilter(new IndicesCallbackFilter(declaringClass, methods)); enhancer.setCallbackTypes(callbackTypes); return new ProxyConstructor(enhancer, injectionPoint, callbacks, interceptors); } catch (Throwable e) { throw new Errors().errorEnhancingClass(declaringClass, e).toException(); } } private static class MethodInterceptorsPair { final Method method; List interceptors; // lazy MethodInterceptorsPair(Method method) { this.method = method; } void addAll(List interceptors) { if (this.interceptors == null) { this.interceptors = Lists.newArrayList(); } this.interceptors.addAll(interceptors); } boolean hasInterceptors() { return interceptors != null; } } /** * A callback filter that maps methods to unique IDs. We define equals and hashCode using the * declaring class so that enhanced classes can be shared between injectors. */ private static class IndicesCallbackFilter implements CallbackFilter { final Class declaringClass; final Map indices; IndicesCallbackFilter(Class declaringClass, List methods) { this.declaringClass = declaringClass; final Map indices = Maps.newHashMap(); for (int i = 0; i < methods.size(); i++) { Method method = methods.get(i); indices.put(method, i); } this.indices = indices; } public int accept(Method method) { return indices.get(method); } @Override public boolean equals(Object o) { return o instanceof IndicesCallbackFilter && ((IndicesCallbackFilter) o).declaringClass == declaringClass; } @Override public int hashCode() { return declaringClass.hashCode(); } } /** * Constructs instances that participate in AOP. */ private static class ProxyConstructor implements ConstructionProxy { final Class enhanced; final InjectionPoint injectionPoint; final Constructor constructor; final Callback[] callbacks; final FastConstructor fastConstructor; final ImmutableMap> methodInterceptors; @SuppressWarnings("unchecked") // the constructor promises to construct 'T's ProxyConstructor(Enhancer enhancer, InjectionPoint injectionPoint, Callback[] callbacks, ImmutableMap> methodInterceptors) { this.enhanced = enhancer.createClass(); // this returns a cached class if possible this.injectionPoint = injectionPoint; this.constructor = (Constructor) injectionPoint.getMember(); this.callbacks = callbacks; this.methodInterceptors = methodInterceptors; FastClass fastClass = newFastClass(enhanced, BytecodeGen.Visibility.forMember(constructor)); this.fastConstructor = fastClass.getConstructor(constructor.getParameterTypes()); } @SuppressWarnings("unchecked") // the constructor promises to produce 'T's public T newInstance(Object... arguments) throws InvocationTargetException { Enhancer.registerCallbacks(enhanced, callbacks); try { return (T) fastConstructor.newInstance(arguments); } finally { Enhancer.registerCallbacks(enhanced, null); } } public InjectionPoint getInjectionPoint() { return injectionPoint; } public Constructor getConstructor() { return constructor; } public ImmutableMap> getMethodInterceptors() { return methodInterceptors; } } } guice-3.0/core/src/com/google/inject/internal/Lookups.java0000644000175000017500000000212211460133000023465 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Key; import com.google.inject.MembersInjector; import com.google.inject.Provider; import com.google.inject.TypeLiteral; /** * Accessors for providers and members injectors. The returned values will not be functional until * the injector has been created. * * @author jessewilson@google.com (Jesse Wilson) */ interface Lookups { Provider getProvider(Key key); MembersInjector getMembersInjector(TypeLiteral type); } guice-3.0/core/src/com/google/inject/internal/InterceptorBindingProcessor.java0000644000175000017500000000227011460133000027526 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.spi.InterceptorBinding; /** * Handles {@code Binder.bindInterceptor} commands. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ final class InterceptorBindingProcessor extends AbstractProcessor { InterceptorBindingProcessor(Errors errors) { super(errors); } @Override public Boolean visit(InterceptorBinding command) { injector.state.addMethodAspect(new MethodAspect( command.getClassMatcher(), command.getMethodMatcher(), command.getInterceptors())); return true; } } guice-3.0/core/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java0000644000175000017500000000372311460134242030475 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.spi.Dependency; /** * @author crazybob@google.com (Bob Lee) */ final class ProviderToInternalFactoryAdapter implements Provider { private final InjectorImpl injector; private final InternalFactory internalFactory; public ProviderToInternalFactoryAdapter(InjectorImpl injector, InternalFactory internalFactory) { this.injector = injector; this.internalFactory = internalFactory; } public T get() { final Errors errors = new Errors(); try { T t = injector.callInContext(new ContextualCallable() { public T call(InternalContext context) throws ErrorsException { Dependency dependency = context.getDependency(); // Always pretend that we are a linked binding, to support // scoping implicit bindings. If we are not actually a linked // binding, we'll fail properly elsewhere in the chain. return internalFactory.get(errors, context, dependency, true); } }); errors.throwIfNewErrors(0); return t; } catch (ErrorsException e) { throw new ProvisionException(errors.merge(e.getErrors()).getMessages()); } } @Override public String toString() { return internalFactory.toString(); } } guice-3.0/core/src/com/google/inject/internal/ConstantBindingBuilderImpl.java0000644000175000017500000000721411461101156027265 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.binder.AnnotatedConstantBindingBuilder; import com.google.inject.binder.ConstantBindingBuilder; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.spi.Element; import com.google.inject.spi.InjectionPoint; import java.lang.annotation.Annotation; import java.util.List; /** * Bind a constant. * * @author jessewilson@google.com (Jesse Wilson) */ public final class ConstantBindingBuilderImpl extends AbstractBindingBuilder implements AnnotatedConstantBindingBuilder, ConstantBindingBuilder { @SuppressWarnings("unchecked") // constant bindings start out with T unknown public ConstantBindingBuilderImpl(Binder binder, List elements, Object source) { super(binder, elements, source, (Key) NULL_KEY); } public ConstantBindingBuilder annotatedWith(Class annotationType) { annotatedWithInternal(annotationType); return this; } public ConstantBindingBuilder annotatedWith(Annotation annotation) { annotatedWithInternal(annotation); return this; } public void to(final String value) { toConstant(String.class, value); } public void to(final int value) { toConstant(Integer.class, value); } public void to(final long value) { toConstant(Long.class, value); } public void to(final boolean value) { toConstant(Boolean.class, value); } public void to(final double value) { toConstant(Double.class, value); } public void to(final float value) { toConstant(Float.class, value); } public void to(final short value) { toConstant(Short.class, value); } public void to(final char value) { toConstant(Character.class, value); } public void to(final byte value) { toConstant(Byte.class, value); } public void to(final Class value) { toConstant(Class.class, value); } public > void to(final E value) { toConstant(value.getDeclaringClass(), value); } private void toConstant(Class type, Object instance) { // this type will define T, so these assignments are safe @SuppressWarnings("unchecked") Class typeAsClassT = (Class) type; @SuppressWarnings("unchecked") T instanceAsT = (T) instance; if (keyTypeIsSet()) { binder.addError(CONSTANT_VALUE_ALREADY_SET); return; } BindingImpl base = getBinding(); Key key; if (base.getKey().getAnnotation() != null) { key = Key.get(typeAsClassT, base.getKey().getAnnotation()); } else if (base.getKey().getAnnotationType() != null) { key = Key.get(typeAsClassT, base.getKey().getAnnotationType()); } else { key = Key.get(typeAsClassT); } if (instanceAsT == null) { binder.addError(BINDING_TO_NULL); } setBinding(new InstanceBindingImpl( base.getSource(), key, base.getScoping(), ImmutableSet.of(), instanceAsT)); } @Override public String toString() { return "ConstantBindingBuilder"; } }guice-3.0/core/src/com/google/inject/internal/ConstructorInjectorStore.java0000644000175000017500000000674611460133000027111 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.util.ImmutableList; import static com.google.inject.internal.util.Iterables.concat; import com.google.inject.spi.InjectionPoint; /** * Constructor injectors by type. * * @author jessewilson@google.com (Jesse Wilson) */ final class ConstructorInjectorStore { private final InjectorImpl injector; private final FailableCache> cache = new FailableCache> () { @SuppressWarnings("unchecked") protected ConstructorInjector create(InjectionPoint constructorInjector, Errors errors) throws ErrorsException { return createConstructor(constructorInjector, errors); } }; ConstructorInjectorStore(InjectorImpl injector) { this.injector = injector; } /** * Returns a new complete constructor injector with injection listeners registered. */ public ConstructorInjector get(InjectionPoint constructorInjector, Errors errors) throws ErrorsException { return cache.get(constructorInjector, errors); } /** * Purges an injection point from the cache. Use this only if the cache is not actually valid and * needs to be purged. (See issue 319 and * ImplicitBindingTest#testCircularJitBindingsLeaveNoResidue and * #testInstancesRequestingProvidersForThemselvesWithChildInjectors for examples of when this is * necessary.) * * Returns true if the injector for that point was stored in the cache, false otherwise. */ boolean remove(InjectionPoint ip) { return cache.remove(ip); } private ConstructorInjector createConstructor(InjectionPoint injectionPoint, Errors errors) throws ErrorsException { int numErrorsBefore = errors.size(); SingleParameterInjector[] constructorParameterInjectors = injector.getParametersInjectors(injectionPoint.getDependencies(), errors); @SuppressWarnings("unchecked") // the injector type agrees with the injection point type MembersInjectorImpl membersInjector = (MembersInjectorImpl) injector.membersInjectorStore .get(injectionPoint.getDeclaringType(), errors); /*if[AOP]*/ ImmutableList injectorAspects = injector.state.getMethodAspects(); ImmutableList methodAspects = membersInjector.getAddedAspects().isEmpty() ? injectorAspects : ImmutableList.copyOf(concat(injectorAspects, membersInjector.getAddedAspects())); ConstructionProxyFactory factory = new ProxyFactory(injectionPoint, methodAspects); /*end[AOP]*/ /*if[NO_AOP] ConstructionProxyFactory factory = new DefaultConstructionProxyFactory(injectionPoint); end[NO_AOP]*/ errors.throwIfNewErrors(numErrorsBefore); return new ConstructorInjector(membersInjector.getInjectionPoints(), factory.create(), constructorParameterInjectors, membersInjector); } } guice-3.0/core/src/com/google/inject/internal/FactoryProxy.java0000644000175000017500000000416211536227460024532 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Key; import com.google.inject.internal.InjectorImpl.JitLimitation; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.Dependency; /** * A placeholder which enables us to swap in the real factory once the injector is created. * Used for a linked binding, so that getting the linked binding returns the link's factory. */ final class FactoryProxy implements InternalFactory, CreationListener { private final InjectorImpl injector; private final Key key; private final Key targetKey; private final Object source; private InternalFactory targetFactory; FactoryProxy(InjectorImpl injector, Key key, Key targetKey, Object source) { this.injector = injector; this.key = key; this.targetKey = targetKey; this.source = source; } public void notify(final Errors errors) { try { targetFactory = injector.getInternalFactory(targetKey, errors.withSource(source), JitLimitation.NEW_OR_EXISTING_JIT); } catch (ErrorsException e) { errors.merge(e.getErrors()); } } public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) throws ErrorsException { return targetFactory.get(errors.withSource(targetKey), context, dependency, true); } @Override public String toString() { return new ToStringBuilder(FactoryProxy.class) .add("key", key) .add("provider", targetFactory) .toString(); } } guice-3.0/core/src/com/google/inject/internal/LinkedBindingImpl.java0000644000175000017500000000615211460133000025363 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Objects; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.LinkedKeyBinding; import java.util.Set; public final class LinkedBindingImpl extends BindingImpl implements LinkedKeyBinding, HasDependencies { final Key targetKey; public LinkedBindingImpl(InjectorImpl injector, Key key, Object source, InternalFactory internalFactory, Scoping scoping, Key targetKey) { super(injector, key, source, internalFactory, scoping); this.targetKey = targetKey; } public LinkedBindingImpl(Object source, Key key, Scoping scoping, Key targetKey) { super(source, key, scoping); this.targetKey = targetKey; } public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } public Key getLinkedKey() { return targetKey; } public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(targetKey)); } public BindingImpl withScoping(Scoping scoping) { return new LinkedBindingImpl(getSource(), getKey(), scoping, targetKey); } public BindingImpl withKey(Key key) { return new LinkedBindingImpl(getSource(), key, getScoping(), targetKey); } public void applyTo(Binder binder) { getScoping().applyTo(binder.withSource(getSource()).bind(getKey()).to(getLinkedKey())); } @Override public String toString() { return new ToStringBuilder(LinkedKeyBinding.class) .add("key", getKey()) .add("source", getSource()) .add("scope", getScoping()) .add("target", targetKey) .toString(); } @Override public boolean equals(Object obj) { if(obj instanceof LinkedBindingImpl) { LinkedBindingImpl o = (LinkedBindingImpl)obj; return getKey().equals(o.getKey()) && getScoping().equals(o.getScoping()) && Objects.equal(targetKey, o.targetKey); } else { return false; } } @Override public int hashCode() { return Objects.hashCode(getKey(), getScoping(), targetKey); } } guice-3.0/core/src/com/google/inject/internal/Initializer.java0000644000175000017500000001343211460133000024322 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Stage; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Maps; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.spi.InjectionPoint; import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; /** * Manages and injects instances at injector-creation time. This is made more complicated by * instances that request other instances while they're being injected. We overcome this by using * {@link Initializable}, which attempts to perform injection before use. * * @author jessewilson@google.com (Jesse Wilson) */ final class Initializer { /** the only thread that we'll use to inject members. */ private final Thread creatingThread = Thread.currentThread(); /** zero means everything is injected. */ private final CountDownLatch ready = new CountDownLatch(1); /** Maps instances that need injection to a source that registered them */ private final Map> pendingInjection = Maps.newIdentityHashMap(); /** * Registers an instance for member injection when that step is performed. * * @param instance an instance that optionally has members to be injected (each annotated with * @Inject). * @param source the source location that this injection was requested */ Initializable requestInjection(InjectorImpl injector, T instance, Object source, Set injectionPoints) { checkNotNull(source); // short circuit if the object has no injections if (instance == null || (injectionPoints.isEmpty() && !injector.membersInjectorStore.hasTypeListeners())) { return Initializables.of(instance); } InjectableReference initializable = new InjectableReference(injector, instance, source); pendingInjection.put(instance, initializable); return initializable; } /** * Prepares member injectors for all injected instances. This prompts Guice to do static analysis * on the injected instances. */ void validateOustandingInjections(Errors errors) { for (InjectableReference reference : pendingInjection.values()) { try { reference.validate(errors); } catch (ErrorsException e) { errors.merge(e.getErrors()); } } } /** * Performs creation-time injections on all objects that require it. Whenever fulfilling an * injection depends on another object that requires injection, we inject it first. If the two * instances are codependent (directly or transitively), ordering of injection is arbitrary. */ void injectAll(final Errors errors) { // loop over a defensive copy since ensureInjected() mutates the set. Unfortunately, that copy // is made complicated by a bug in IBM's JDK, wherein entrySet().toArray(Object[]) doesn't work for (InjectableReference reference : Lists.newArrayList(pendingInjection.values())) { try { reference.get(errors); } catch (ErrorsException e) { errors.merge(e.getErrors()); } } if (!pendingInjection.isEmpty()) { throw new AssertionError("Failed to satisfy " + pendingInjection); } ready.countDown(); } private class InjectableReference implements Initializable { private final InjectorImpl injector; private final T instance; private final Object source; private MembersInjectorImpl membersInjector; public InjectableReference(InjectorImpl injector, T instance, Object source) { this.injector = injector; this.instance = checkNotNull(instance, "instance"); this.source = checkNotNull(source, "source"); } public void validate(Errors errors) throws ErrorsException { @SuppressWarnings("unchecked") // the type of 'T' is a TypeLiteral TypeLiteral type = TypeLiteral.get((Class) instance.getClass()); membersInjector = injector.membersInjectorStore.get(type, errors.withSource(source)); } /** * Reentrant. If {@code instance} was registered for injection at injector-creation time, this * method will ensure that all its members have been injected before returning. */ public T get(Errors errors) throws ErrorsException { if (ready.getCount() == 0) { return instance; } // just wait for everything to be injected by another thread if (Thread.currentThread() != creatingThread) { try { ready.await(); return instance; } catch (InterruptedException e) { // Give up, since we don't know if our injection is ready throw new RuntimeException(e); } } // toInject needs injection, do it right away. we only do this once, even if it fails if (pendingInjection.remove(instance) != null) { // if in Stage.TOOL, we only want to inject & notify toolable injection points. // (otherwise we'll inject all of them) membersInjector.injectAndNotify(instance, errors.withSource(source), injector.options.stage == Stage.TOOL); } return instance; } @Override public String toString() { return instance.toString(); } } }guice-3.0/core/src/com/google/inject/internal/DefaultConstructionProxyFactory.java0000644000175000017500000000734211460133000030433 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.BytecodeGen.Visibility; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.spi.InjectionPoint; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.List; /** * Produces construction proxies that invoke the class constructor. * * @author crazybob@google.com (Bob Lee) */ final class DefaultConstructionProxyFactory implements ConstructionProxyFactory { private final InjectionPoint injectionPoint; /** * @param injectionPoint an injection point whose member is a constructor of {@code T}. */ DefaultConstructionProxyFactory(InjectionPoint injectionPoint) { this.injectionPoint = injectionPoint; } public ConstructionProxy create() { @SuppressWarnings("unchecked") // the injection point is for a constructor of T final Constructor constructor = (Constructor) injectionPoint.getMember(); // Use FastConstructor if the constructor is public. if (Modifier.isPublic(constructor.getModifiers())) { Class classToConstruct = constructor.getDeclaringClass(); /*if[AOP]*/ try { final net.sf.cglib.reflect.FastConstructor fastConstructor = BytecodeGen.newFastClass(classToConstruct, Visibility.forMember(constructor)) .getConstructor(constructor); return new ConstructionProxy() { @SuppressWarnings("unchecked") public T newInstance(Object... arguments) throws InvocationTargetException { return (T) fastConstructor.newInstance(arguments); } public InjectionPoint getInjectionPoint() { return injectionPoint; } public Constructor getConstructor() { return constructor; } public ImmutableMap> getMethodInterceptors() { return ImmutableMap.of(); } }; } catch (net.sf.cglib.core.CodeGenerationException e) {/* fall-through */} /*end[AOP]*/ if (!Modifier.isPublic(classToConstruct.getModifiers())) { constructor.setAccessible(true); } } else { constructor.setAccessible(true); } return new ConstructionProxy() { public T newInstance(Object... arguments) throws InvocationTargetException { try { return constructor.newInstance(arguments); } catch (InstantiationException e) { throw new AssertionError(e); // shouldn't happen, we know this is a concrete type } catch (IllegalAccessException e) { throw new AssertionError(e); // a security manager is blocking us, we're hosed } } public InjectionPoint getInjectionPoint() { return injectionPoint; } public Constructor getConstructor() { return constructor; } /*if[AOP]*/ public ImmutableMap> getMethodInterceptors() { return ImmutableMap.of(); } /*end[AOP]*/ }; } } guice-3.0/core/src/com/google/inject/internal/CreationListener.java0000644000175000017500000000145611536235614025336 0ustar drazzibdrazzib/** * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; /** Something that is notified upon creation. */ interface CreationListener { /** Notifies that creation should happen. */ void notify(Errors errors); }guice-3.0/core/src/com/google/inject/internal/Exceptions.java0000644000175000017500000000356611461003550024176 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import java.lang.reflect.InvocationTargetException; /** * Rethrows user-code exceptions in wrapped exceptions so that Errors can target the correct * exception. * * @author sameb@google.com (Sam Berlin) */ class Exceptions { /** * Rethrows the exception (or it's cause) directly if possible. If it was a checked exception, * this wraps the exception in a stack trace with no frames, so that the exception is shown * immediately with no frames above it. */ public static RuntimeException throwCleanly(InvocationTargetException exception) { Throwable cause = exception; if(cause.getCause() != null) { cause = cause.getCause(); } if(cause instanceof RuntimeException) { throw (RuntimeException)cause; } else if(cause instanceof Error) { throw (Error)cause; } else { throw new UnhandledCheckedUserException(cause); } } /** * A marker exception class that we look for in order to unwrap the exception * into the user exception, to provide a cleaner stack trace. */ static class UnhandledCheckedUserException extends RuntimeException { public UnhandledCheckedUserException(Throwable cause) { super(cause); } } } guice-3.0/core/src/com/google/inject/internal/BindingImpl.java0000644000175000017500000000615311460133000024235 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.BindingScopingVisitor; import com.google.inject.spi.ElementVisitor; import com.google.inject.spi.InstanceBinding; /** * @author crazybob@google.com (Bob Lee) */ public abstract class BindingImpl implements Binding { private final InjectorImpl injector; private final Key key; private final Object source; private final Scoping scoping; private final InternalFactory internalFactory; public BindingImpl(InjectorImpl injector, Key key, Object source, InternalFactory internalFactory, Scoping scoping) { this.injector = injector; this.key = key; this.source = source; this.internalFactory = internalFactory; this.scoping = scoping; } protected BindingImpl(Object source, Key key, Scoping scoping) { this.internalFactory = null; this.injector = null; this.source = source; this.key = key; this.scoping = scoping; } public Key getKey() { return key; } public Object getSource() { return source; } private volatile Provider provider; public Provider getProvider() { if (provider == null) { if (injector == null) { throw new UnsupportedOperationException("getProvider() not supported for module bindings"); } provider = injector.getProvider(key); } return provider; } public InternalFactory getInternalFactory() { return internalFactory; } public Scoping getScoping() { return scoping; } /** * Is this a constant binding? This returns true for constant bindings as * well as toInstance() bindings. */ public boolean isConstant() { return this instanceof InstanceBinding; } public V acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } public V acceptScopingVisitor(BindingScopingVisitor visitor) { return scoping.acceptVisitor(visitor); } protected BindingImpl withScoping(Scoping scoping) { throw new AssertionError(); } protected BindingImpl withKey(Key key) { throw new AssertionError(); } @Override public String toString() { return new ToStringBuilder(Binding.class) .add("key", key) .add("scope", scoping) .add("source", source) .toString(); } public InjectorImpl getInjector() { return injector; } }guice-3.0/core/src/com/google/inject/internal/ConstructorBindingImpl.java0000644000175000017500000002450211530443574026523 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.ConfigurationException; import com.google.inject.Key; import com.google.inject.TypeLiteral; import static com.google.inject.internal.Annotations.findScopeAnnotation; import com.google.inject.internal.util.Classes; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Objects; import static com.google.inject.internal.util.Preconditions.checkState; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.ConstructorBinding; import com.google.inject.spi.Dependency; import com.google.inject.spi.InjectionPoint; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.List; import java.util.Map; import java.util.Set; final class ConstructorBindingImpl extends BindingImpl implements ConstructorBinding { private final Factory factory; private final InjectionPoint constructorInjectionPoint; private ConstructorBindingImpl(InjectorImpl injector, Key key, Object source, InternalFactory scopedFactory, Scoping scoping, Factory factory, InjectionPoint constructorInjectionPoint) { super(injector, key, source, scopedFactory, scoping); this.factory = factory; this.constructorInjectionPoint = constructorInjectionPoint; } public ConstructorBindingImpl(Key key, Object source, Scoping scoping, InjectionPoint constructorInjectionPoint, Set injectionPoints) { super(source, key, scoping); this.factory = new Factory(false, key); ConstructionProxy constructionProxy = new DefaultConstructionProxyFactory(constructorInjectionPoint).create(); this.constructorInjectionPoint = constructorInjectionPoint; factory.constructorInjector = new ConstructorInjector( injectionPoints, constructionProxy, null, null); } /** * @param constructorInjector the constructor to use, or {@code null} to use the default. * @param failIfNotLinked true if this ConstructorBindingImpl's InternalFactory should * only succeed if retrieved from a linked binding */ static ConstructorBindingImpl create(InjectorImpl injector, Key key, InjectionPoint constructorInjector, Object source, Scoping scoping, Errors errors, boolean failIfNotLinked) throws ErrorsException { int numErrors = errors.size(); @SuppressWarnings("unchecked") // constructorBinding guarantees type is consistent Class rawType = constructorInjector == null ? key.getTypeLiteral().getRawType() : (Class) constructorInjector.getDeclaringType().getRawType(); // We can't inject abstract classes. if (Modifier.isAbstract(rawType.getModifiers())) { errors.missingImplementation(key); } // Error: Inner class. if (Classes.isInnerClass(rawType)) { errors.cannotInjectInnerClass(rawType); } errors.throwIfNewErrors(numErrors); // Find a constructor annotated @Inject if (constructorInjector == null) { try { constructorInjector = InjectionPoint.forConstructorOf(key.getTypeLiteral()); } catch (ConfigurationException e) { throw errors.merge(e.getErrorMessages()).toException(); } } // if no scope is specified, look for a scoping annotation on the concrete class if (!scoping.isExplicitlyScoped()) { Class annotatedType = constructorInjector.getMember().getDeclaringClass(); Class scopeAnnotation = findScopeAnnotation(errors, annotatedType); if (scopeAnnotation != null) { scoping = Scoping.makeInjectable(Scoping.forAnnotation(scopeAnnotation), injector, errors.withSource(rawType)); } } errors.throwIfNewErrors(numErrors); Factory factoryFactory = new Factory(failIfNotLinked, key); InternalFactory scopedFactory = Scoping.scope(key, injector, factoryFactory, source, scoping); return new ConstructorBindingImpl( injector, key, source, scopedFactory, scoping, factoryFactory, constructorInjector); } @SuppressWarnings("unchecked") // the result type always agrees with the ConstructorInjector type public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { factory.allowCircularProxy = !injector.options.disableCircularProxies; factory.constructorInjector = (ConstructorInjector) injector.constructors.get(constructorInjectionPoint, errors); } /** True if this binding has been initialized and is ready for use. */ boolean isInitialized() { return factory.constructorInjector != null; } /** Returns an injection point that can be used to clean up the constructor store. */ InjectionPoint getInternalConstructor() { if(factory.constructorInjector != null) { return factory.constructorInjector.getConstructionProxy().getInjectionPoint(); } else { return constructorInjectionPoint; } } /** Returns a set of dependencies that can be iterated over to clean up stray JIT bindings. */ Set> getInternalDependencies() { ImmutableSet.Builder builder = ImmutableSet.builder(); if(factory.constructorInjector == null) { builder.add(constructorInjectionPoint); // If the below throws, it's OK -- we just ignore those dependencies, because no one // could have used them anyway. try { builder.addAll(InjectionPoint.forInstanceMethodsAndFields(constructorInjectionPoint.getDeclaringType())); } catch(ConfigurationException ignored) {} } else { builder.add(getConstructor()) .addAll(getInjectableMembers()); } return Dependency.forInjectionPoints(builder.build()); } public V acceptTargetVisitor(BindingTargetVisitor visitor) { checkState(factory.constructorInjector != null, "not initialized"); return visitor.visit(this); } public InjectionPoint getConstructor() { checkState(factory.constructorInjector != null, "Binding is not ready"); return factory.constructorInjector.getConstructionProxy().getInjectionPoint(); } public Set getInjectableMembers() { checkState(factory.constructorInjector != null, "Binding is not ready"); return factory.constructorInjector.getInjectableMembers(); } /*if[AOP]*/ public Map> getMethodInterceptors() { checkState(factory.constructorInjector != null, "Binding is not ready"); return factory.constructorInjector.getConstructionProxy().getMethodInterceptors(); } /*end[AOP]*/ public Set> getDependencies() { return Dependency.forInjectionPoints(new ImmutableSet.Builder() .add(getConstructor()) .addAll(getInjectableMembers()) .build()); } @Override protected BindingImpl withScoping(Scoping scoping) { return new ConstructorBindingImpl( null, getKey(), getSource(), factory, scoping, factory, constructorInjectionPoint); } @Override protected BindingImpl withKey(Key key) { return new ConstructorBindingImpl( null, key, getSource(), factory, getScoping(), factory, constructorInjectionPoint); } @SuppressWarnings("unchecked") // the raw constructor member and declaring type always agree public void applyTo(Binder binder) { InjectionPoint constructor = getConstructor(); getScoping().applyTo(binder.withSource(getSource()).bind(getKey()).toConstructor( (Constructor) getConstructor().getMember(), (TypeLiteral) constructor.getDeclaringType())); } @Override public String toString() { return new ToStringBuilder(ConstructorBinding.class) .add("key", getKey()) .add("source", getSource()) .add("scope", getScoping()) .toString(); } @Override public boolean equals(Object obj) { if(obj instanceof ConstructorBindingImpl) { ConstructorBindingImpl o = (ConstructorBindingImpl)obj; return getKey().equals(o.getKey()) && getScoping().equals(o.getScoping()) && Objects.equal(constructorInjectionPoint, o.constructorInjectionPoint); } else { return false; } } @Override public int hashCode() { return Objects.hashCode(getKey(), getScoping(), constructorInjectionPoint); } private static class Factory implements InternalFactory { private final boolean failIfNotLinked; private final Key key; private boolean allowCircularProxy; private ConstructorInjector constructorInjector; Factory(boolean failIfNotLinked, Key key) { this.failIfNotLinked = failIfNotLinked; this.key = key; } @SuppressWarnings("unchecked") public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) throws ErrorsException { checkState(constructorInjector != null, "Constructor not ready"); if(failIfNotLinked && !linked) { throw errors.jitDisabled(key).toException(); } // This may not actually be safe because it could return a super type of T (if that's all the // client needs), but it should be OK in practice thanks to the wonders of erasure. return (T) constructorInjector.construct(errors, context, dependency.getKey().getTypeLiteral().getRawType(), allowCircularProxy); } } } guice-3.0/core/src/com/google/inject/internal/LookupProcessor.java0000644000175000017500000000346311460133000025213 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.MembersInjector; import com.google.inject.Provider; import com.google.inject.spi.MembersInjectorLookup; import com.google.inject.spi.ProviderLookup; /** * Handles {@code Binder.getProvider} and {@code Binder.getMembersInjector(TypeLiteral)} commands. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ final class LookupProcessor extends AbstractProcessor { LookupProcessor(Errors errors) { super(errors); } @Override public Boolean visit(MembersInjectorLookup lookup) { try { MembersInjector membersInjector = injector.membersInjectorStore.get(lookup.getType(), errors); lookup.initializeDelegate(membersInjector); } catch (ErrorsException e) { errors.merge(e.getErrors()); // TODO: source } return true; } @Override public Boolean visit(ProviderLookup lookup) { // ensure the provider can be created try { Provider provider = injector.getProviderOrThrow(lookup.getKey(), errors); lookup.initializeDelegate(provider); } catch (ErrorsException e) { errors.merge(e.getErrors()); // TODO: source } return true; } } guice-3.0/core/src/com/google/inject/internal/InstanceBindingImpl.java0000644000175000017500000000730711464100262025734 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Objects; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.InstanceBinding; import com.google.inject.util.Providers; import java.util.Set; final class InstanceBindingImpl extends BindingImpl implements InstanceBinding { final T instance; final Provider provider; final ImmutableSet injectionPoints; public InstanceBindingImpl(InjectorImpl injector, Key key, Object source, InternalFactory internalFactory, Set injectionPoints, T instance) { super(injector, key, source, internalFactory, Scoping.EAGER_SINGLETON); this.injectionPoints = ImmutableSet.copyOf(injectionPoints); this.instance = instance; this.provider = Providers.of(instance); } public InstanceBindingImpl(Object source, Key key, Scoping scoping, Set injectionPoints, T instance) { super(source, key, scoping); this.injectionPoints = ImmutableSet.copyOf(injectionPoints); this.instance = instance; this.provider = Providers.of(instance); } @Override public Provider getProvider() { return this.provider; } public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } public T getInstance() { return instance; } public Set getInjectionPoints() { return injectionPoints; } public Set> getDependencies() { return instance instanceof HasDependencies ? ImmutableSet.copyOf(((HasDependencies) instance).getDependencies()) : Dependency.forInjectionPoints(injectionPoints); } public BindingImpl withScoping(Scoping scoping) { return new InstanceBindingImpl(getSource(), getKey(), scoping, injectionPoints, instance); } public BindingImpl withKey(Key key) { return new InstanceBindingImpl(getSource(), key, getScoping(), injectionPoints, instance); } public void applyTo(Binder binder) { // instance bindings aren't scoped binder.withSource(getSource()).bind(getKey()).toInstance(instance); } @Override public String toString() { return new ToStringBuilder(InstanceBinding.class) .add("key", getKey()) .add("source", getSource()) .add("instance", instance) .toString(); } @Override public boolean equals(Object obj) { if(obj instanceof InstanceBindingImpl) { InstanceBindingImpl o = (InstanceBindingImpl)obj; return getKey().equals(o.getKey()) && getScoping().equals(o.getScoping()) && Objects.equal(instance, o.instance); } else { return false; } } @Override public int hashCode() { return Objects.hashCode(getKey(), getScoping()); } } guice-3.0/core/src/com/google/inject/internal/ConstantFactory.java0000644000175000017500000000244111460133000025156 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.Dependency; /** * @author crazybob@google.com (Bob Lee) */ final class ConstantFactory implements InternalFactory { private final Initializable initializable; public ConstantFactory(Initializable initializable) { this.initializable = initializable; } public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) throws ErrorsException { return initializable.get(errors); } public String toString() { return new ToStringBuilder(ConstantFactory.class) .add("value", initializable) .toString(); } } guice-3.0/core/src/com/google/inject/internal/ConstructionProxy.java0000644000175000017500000000332311460133000025571 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.spi.InjectionPoint; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; /** * Proxies calls to a {@link java.lang.reflect.Constructor} for a class * {@code T}. * * @author crazybob@google.com (Bob Lee) */ interface ConstructionProxy { /** * Constructs an instance of {@code T} for the given arguments. */ T newInstance(Object... arguments) throws InvocationTargetException; /** * Returns the injection point for this constructor. */ InjectionPoint getInjectionPoint(); /** * Returns the injected constructor. If the injected constructor is synthetic (such as generated * code for method interception), the natural constructor is returned. */ Constructor getConstructor(); /*if[AOP]*/ /** * Returns the interceptors applied to each method, in order of invocation. */ ImmutableMap> getMethodInterceptors(); /*end[AOP]*/ } guice-3.0/core/src/com/google/inject/internal/BytecodeGen.java0000644000175000017500000003043311477775426024267 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.util.Function; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.MapMaker; import com.google.inject.internal.util.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Map; import java.util.logging.Logger; /** * Utility methods for runtime code generation and class loading. We use this stuff for {@link * net.sf.cglib.reflect.FastClass faster reflection}, {@link net.sf.cglib.proxy.Enhancer method * interceptors} and to proxy circular dependencies. * *

When loading classes, we need to be careful of: *

    *
  • Memory leaks. Generated classes need to be garbage collected in long-lived * applications. Once an injector and any instances it created can be garbage collected, the * corresponding generated classes should be collectable. *
  • Visibility. Containers like OSGi use class loader boundaries * to enforce modularity at runtime. *
* *

For each generated class, there's multiple class loaders involved: *

    *
  • The related class's class loader. Every generated class services exactly * one user-supplied class. This class loader must be used to access members with private and * package visibility. *
  • Guice's class loader. *
  • Our bridge class loader. This is a child of the user's class loader. It * selectively delegates to either the user's class loader (for user classes) or the Guice * class loader (for internal classes that are used by the generated classes). This class * loader that owns the classes generated by Guice. *
* * @author mcculls@gmail.com (Stuart McCulloch) * @author jessewilson@google.com (Jesse Wilson) */ public final class BytecodeGen { static final Logger logger = Logger.getLogger(BytecodeGen.class.getName()); static final ClassLoader GUICE_CLASS_LOADER = canonicalize(BytecodeGen.class.getClassLoader()); // initialization-on-demand... private static class SystemBridgeHolder { static final BridgeClassLoader SYSTEM_BRIDGE = new BridgeClassLoader(); } /** ie. "com.google.inject.internal" */ static final String GUICE_INTERNAL_PACKAGE = BytecodeGen.class.getName().replaceFirst("\\.internal\\..*$", ".internal"); /*if[AOP]*/ /** either "net.sf.cglib", or "com.google.inject.internal.cglib" */ static final String CGLIB_PACKAGE = net.sf.cglib.proxy.Enhancer.class.getName().replaceFirst("\\.cglib\\..*$", ".cglib"); static final net.sf.cglib.core.NamingPolicy FASTCLASS_NAMING_POLICY = new net.sf.cglib.core.DefaultNamingPolicy() { @Override protected String getTag() { return "ByGuice"; } @Override public String getClassName(String prefix, String source, Object key, net.sf.cglib.core.Predicate names) { // we explicitly set the source here to "FastClass" so that our jarjar renaming // to $FastClass doesn't leak into the class names. if we did not do this, // classes would end up looking like $$$FastClassByGuice$$, with the extra $ // at the front. return super.getClassName(prefix, "FastClass", key, names); } }; static final net.sf.cglib.core.NamingPolicy ENHANCER_NAMING_POLICY = new net.sf.cglib.core.DefaultNamingPolicy() { @Override protected String getTag() { return "ByGuice"; } @Override public String getClassName(String prefix, String source, Object key, net.sf.cglib.core.Predicate names) { // we explicitly set the source here to "Enhancer" so that our jarjar renaming // to $Enhancer doesn't leak into the class names. if we did not do this, // classes would end up looking like $$$EnhancerByGuice$$, with the extra $ // at the front. return super.getClassName(prefix, "Enhancer", key, names); } }; /*end[AOP]*/ /*if[NO_AOP] private static final String CGLIB_PACKAGE = " "; // any string that's illegal in a package name end[NO_AOP]*/ /** Use "-Dguice.custom.loader=false" to disable custom classloading. */ private static final boolean CUSTOM_LOADER_ENABLED = Boolean.parseBoolean(System.getProperty("guice.custom.loader", "true")); /** * Weak cache of bridge class loaders that make the Guice implementation * classes visible to various code-generated proxies of client classes. */ private static final Map CLASS_LOADER_CACHE; static { if (CUSTOM_LOADER_ENABLED) { CLASS_LOADER_CACHE = new MapMaker().weakKeys().weakValues().makeComputingMap( new Function() { public ClassLoader apply(final @Nullable ClassLoader typeClassLoader) { logger.fine("Creating a bridge ClassLoader for " + typeClassLoader); return AccessController.doPrivileged(new PrivilegedAction() { public ClassLoader run() { return new BridgeClassLoader(typeClassLoader); } }); } }); } else { CLASS_LOADER_CACHE = ImmutableMap.of(); } } /** * Attempts to canonicalize null references to the system class loader. * May return null if for some reason the system loader is unavailable. */ private static ClassLoader canonicalize(ClassLoader classLoader) { return classLoader != null ? classLoader : SystemBridgeHolder.SYSTEM_BRIDGE.getParent(); } /** * Returns the class loader to host generated classes for {@code type}. */ public static ClassLoader getClassLoader(Class type) { return getClassLoader(type, type.getClassLoader()); } private static ClassLoader getClassLoader(Class type, ClassLoader delegate) { // simple case: do nothing! if (!CUSTOM_LOADER_ENABLED) { return delegate; } // java.* types can be seen everywhere if (type.getName().startsWith("java.")) { return GUICE_CLASS_LOADER; } delegate = canonicalize(delegate); // no need for a bridge if using same class loader, or it's already a bridge if (delegate == GUICE_CLASS_LOADER || delegate instanceof BridgeClassLoader) { return delegate; } // don't try bridging private types as it won't work if (Visibility.forType(type) == Visibility.PUBLIC) { if (delegate != SystemBridgeHolder.SYSTEM_BRIDGE.getParent()) { // delegate guaranteed to be non-null here return CLASS_LOADER_CACHE.get(delegate); } // delegate may or may not be null here return SystemBridgeHolder.SYSTEM_BRIDGE; } return delegate; // last-resort: do nothing! } /*if[AOP]*/ // use fully-qualified names so imports don't need preprocessor statements public static net.sf.cglib.reflect.FastClass newFastClass(Class type, Visibility visibility) { net.sf.cglib.reflect.FastClass.Generator generator = new net.sf.cglib.reflect.FastClass.Generator(); generator.setType(type); if (visibility == Visibility.PUBLIC) { generator.setClassLoader(getClassLoader(type)); } generator.setNamingPolicy(FASTCLASS_NAMING_POLICY); logger.fine("Loading " + type + " FastClass with " + generator.getClassLoader()); return generator.create(); } public static net.sf.cglib.proxy.Enhancer newEnhancer(Class type, Visibility visibility) { net.sf.cglib.proxy.Enhancer enhancer = new net.sf.cglib.proxy.Enhancer(); enhancer.setSuperclass(type); enhancer.setUseFactory(false); if (visibility == Visibility.PUBLIC) { enhancer.setClassLoader(getClassLoader(type)); } enhancer.setNamingPolicy(ENHANCER_NAMING_POLICY); logger.fine("Loading " + type + " Enhancer with " + enhancer.getClassLoader()); return enhancer; } /*end[AOP]*/ /** * The required visibility of a user's class from a Guice-generated class. Visibility of * package-private members depends on the loading classloader: only if two classes were loaded by * the same classloader can they see each other's package-private members. We need to be careful * when choosing which classloader to use for generated classes. We prefer our bridge classloader, * since it's OSGi-safe and doesn't leak permgen space. But often we cannot due to visibility. */ public enum Visibility { /** * Indicates that Guice-generated classes only need to call and override public members of the * target class. These generated classes may be loaded by our bridge classloader. */ PUBLIC { @Override public Visibility and(Visibility that) { return that; } }, /** * Indicates that Guice-generated classes need to call or override package-private members. * These generated classes must be loaded in the same classloader as the target class. They * won't work with OSGi, and won't get garbage collected until the target class' classloader is * garbage collected. */ SAME_PACKAGE { @Override public Visibility and(Visibility that) { return this; } }; public static Visibility forMember(Member member) { if ((member.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) { return SAME_PACKAGE; } Class[] parameterTypes; if (member instanceof Constructor) { parameterTypes = ((Constructor) member).getParameterTypes(); } else { Method method = (Method) member; if (forType(method.getReturnType()) == SAME_PACKAGE) { return SAME_PACKAGE; } parameterTypes = method.getParameterTypes(); } for (Class type : parameterTypes) { if (forType(type) == SAME_PACKAGE) { return SAME_PACKAGE; } } return PUBLIC; } public static Visibility forType(Class type) { return (type.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0 ? PUBLIC : SAME_PACKAGE; } public abstract Visibility and(Visibility that); } /** * Loader for Guice-generated classes. For referenced classes, this delegates to either either the * user's classloader (which is the parent of this classloader) or Guice's class loader. */ private static class BridgeClassLoader extends ClassLoader { BridgeClassLoader() { // use system loader as parent } BridgeClassLoader(ClassLoader usersClassLoader) { super(usersClassLoader); } @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { if (name.startsWith("sun.reflect")) { // these reflection classes must be loaded from bootstrap class loader return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve); } if (name.startsWith(GUICE_INTERNAL_PACKAGE) || name.startsWith(CGLIB_PACKAGE)) { if (null == GUICE_CLASS_LOADER) { // use special system bridge to load classes from bootstrap class loader return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve); } try { Class clazz = GUICE_CLASS_LOADER.loadClass(name); if (resolve) { resolveClass(clazz); } return clazz; } catch (Throwable e) { // fall-back to classic delegation } } return classicLoadClass(name, resolve); } // make the classic delegating loadClass method visible Class classicLoadClass(String name, boolean resolve) throws ClassNotFoundException { return super.loadClass(name, resolve); } } } guice-3.0/core/src/com/google/inject/internal/AbstractBindingBuilder.java0000644000175000017500000001067711460133000026414 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.Scope; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.spi.Element; import com.google.inject.spi.InstanceBinding; import java.lang.annotation.Annotation; import java.util.List; /** * Bind a value or constant. * * @author jessewilson@google.com (Jesse Wilson) */ public abstract class AbstractBindingBuilder { public static final String IMPLEMENTATION_ALREADY_SET = "Implementation is set more than once."; public static final String SINGLE_INSTANCE_AND_SCOPE = "Setting the scope is not permitted when binding to a single instance."; public static final String SCOPE_ALREADY_SET = "Scope is set more than once."; public static final String BINDING_TO_NULL = "Binding to null instances is not allowed. " + "Use toProvider(Providers.of(null)) if this is your intended behaviour."; public static final String CONSTANT_VALUE_ALREADY_SET = "Constant value is set more than once."; public static final String ANNOTATION_ALREADY_SPECIFIED = "More than one annotation is specified for this binding."; protected static final Key NULL_KEY = Key.get(Void.class); protected List elements; protected int position; protected final Binder binder; private BindingImpl binding; public AbstractBindingBuilder(Binder binder, List elements, Object source, Key key) { this.binder = binder; this.elements = elements; this.position = elements.size(); this.binding = new UntargettedBindingImpl(source, key, Scoping.UNSCOPED); elements.add(position, this.binding); } protected BindingImpl getBinding() { return binding; } protected BindingImpl setBinding(BindingImpl binding) { this.binding = binding; elements.set(position, binding); return binding; } /** Sets the binding to a copy with the specified annotation on the bound key */ protected BindingImpl annotatedWithInternal(Class annotationType) { checkNotNull(annotationType, "annotationType"); checkNotAnnotated(); return setBinding(binding.withKey( Key.get(this.binding.getKey().getTypeLiteral(), annotationType))); } /** Sets the binding to a copy with the specified annotation on the bound key */ protected BindingImpl annotatedWithInternal(Annotation annotation) { checkNotNull(annotation, "annotation"); checkNotAnnotated(); return setBinding(binding.withKey( Key.get(this.binding.getKey().getTypeLiteral(), annotation))); } public void in(final Class scopeAnnotation) { checkNotNull(scopeAnnotation, "scopeAnnotation"); checkNotScoped(); setBinding(getBinding().withScoping(Scoping.forAnnotation(scopeAnnotation))); } public void in(final Scope scope) { checkNotNull(scope, "scope"); checkNotScoped(); setBinding(getBinding().withScoping(Scoping.forInstance(scope))); } public void asEagerSingleton() { checkNotScoped(); setBinding(getBinding().withScoping(Scoping.EAGER_SINGLETON)); } protected boolean keyTypeIsSet() { return !Void.class.equals(binding.getKey().getTypeLiteral().getType()); } protected void checkNotTargetted() { if (!(binding instanceof UntargettedBindingImpl)) { binder.addError(IMPLEMENTATION_ALREADY_SET); } } protected void checkNotAnnotated() { if (binding.getKey().getAnnotationType() != null) { binder.addError(ANNOTATION_ALREADY_SPECIFIED); } } protected void checkNotScoped() { // Scoping isn't allowed when we have only one instance. if (binding instanceof InstanceBinding) { binder.addError(SINGLE_INSTANCE_AND_SCOPE); return; } if (binding.getScoping().isExplicitlyScoped()) { binder.addError(SCOPE_ALREADY_SET); } } }guice-3.0/core/src/com/google/inject/internal/Errors.java0000644000175000017500000005770111533260340023333 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.ConfigurationException; import com.google.inject.CreationException; import com.google.inject.Key; import com.google.inject.MembersInjector; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.Scope; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Classes; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.SourceProvider; import com.google.inject.internal.util.StackTraceElements; import com.google.inject.spi.Dependency; import com.google.inject.spi.InjectionListener; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.Message; import com.google.inject.spi.TypeConverterBinding; import com.google.inject.spi.TypeListenerBinding; import java.io.PrintWriter; import java.io.Serializable; import java.io.StringWriter; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Formatter; import java.util.List; import java.util.Set; /** * A collection of error messages. If this type is passed as a method parameter, the method is * considered to have executed successfully only if new errors were not added to this collection. * *

Errors can be chained to provide additional context. To add context, call {@link #withSource} * to create a new Errors instance that contains additional context. All messages added to the * returned instance will contain full context. * *

To avoid messages with redundant context, {@link #withSource} should be added sparingly. A * good rule of thumb is to assume a ethod's caller has already specified enough context to * identify that method. When calling a method that's defined in a different context, call that * method with an errors object that includes its context. * * @author jessewilson@google.com (Jesse Wilson) */ public final class Errors implements Serializable { /** * The root errors object. Used to access the list of error messages. */ private final Errors root; /** * The parent errors object. Used to obtain the chain of source objects. */ private final Errors parent; /** * The leaf source for errors added here. */ private final Object source; /** * null unless (root == this) and error messages exist. Never an empty list. */ private List errors; // lazy, use getErrorsForAdd() public Errors() { this.root = this; this.parent = null; this.source = SourceProvider.UNKNOWN_SOURCE; } public Errors(Object source) { this.root = this; this.parent = null; this.source = source; } private Errors(Errors parent, Object source) { this.root = parent.root; this.parent = parent; this.source = source; } /** * Returns an instance that uses {@code source} as a reference point for newly added errors. */ public Errors withSource(Object source) { return source == SourceProvider.UNKNOWN_SOURCE ? this : new Errors(this, source); } /** * We use a fairly generic error message here. The motivation is to share the * same message for both bind time errors: *

Guice.createInjector(new AbstractModule() {
   *   public void configure() {
   *     bind(Runnable.class);
   *   }
   * }
* ...and at provide-time errors: *
Guice.createInjector().getInstance(Runnable.class);
* Otherwise we need to know who's calling when resolving a just-in-time * binding, which makes things unnecessarily complex. */ public Errors missingImplementation(Key key) { return addMessage("No implementation for %s was bound.", key); } public Errors jitDisabled(Key key) { return addMessage("Explicit bindings are required and %s is not explicitly bound.", key); } public Errors converterReturnedNull(String stringValue, Object source, TypeLiteral type, TypeConverterBinding typeConverterBinding) { return addMessage("Received null converting '%s' (bound at %s) to %s%n" + " using %s.", stringValue, convert(source), type, typeConverterBinding); } public Errors conversionTypeError(String stringValue, Object source, TypeLiteral type, TypeConverterBinding typeConverterBinding, Object converted) { return addMessage("Type mismatch converting '%s' (bound at %s) to %s%n" + " using %s.%n" + " Converter returned %s.", stringValue, convert(source), type, typeConverterBinding, converted); } public Errors conversionError(String stringValue, Object source, TypeLiteral type, TypeConverterBinding typeConverterBinding, RuntimeException cause) { return errorInUserCode(cause, "Error converting '%s' (bound at %s) to %s%n" + " using %s.%n" + " Reason: %s", stringValue, convert(source), type, typeConverterBinding, cause); } public Errors ambiguousTypeConversion(String stringValue, Object source, TypeLiteral type, TypeConverterBinding a, TypeConverterBinding b) { return addMessage("Multiple converters can convert '%s' (bound at %s) to %s:%n" + " %s and%n" + " %s.%n" + " Please adjust your type converter configuration to avoid overlapping matches.", stringValue, convert(source), type, a, b); } public Errors bindingToProvider() { return addMessage("Binding to Provider is not allowed."); } public Errors subtypeNotProvided(Class> providerType, Class type) { return addMessage("%s doesn't provide instances of %s.", providerType, type); } public Errors notASubtype(Class implementationType, Class type) { return addMessage("%s doesn't extend %s.", implementationType, type); } public Errors recursiveImplementationType() { return addMessage("@ImplementedBy points to the same class it annotates."); } public Errors recursiveProviderType() { return addMessage("@ProvidedBy points to the same class it annotates."); } public Errors missingRuntimeRetention(Object source) { return addMessage("Please annotate with @Retention(RUNTIME).%n" + " Bound at %s.", convert(source)); } public Errors missingScopeAnnotation() { return addMessage("Please annotate with @ScopeAnnotation."); } public Errors optionalConstructor(Constructor constructor) { return addMessage("%s is annotated @Inject(optional=true), " + "but constructors cannot be optional.", constructor); } public Errors cannotBindToGuiceType(String simpleName) { return addMessage("Binding to core guice framework type is not allowed: %s.", simpleName); } public Errors scopeNotFound(Class scopeAnnotation) { return addMessage("No scope is bound to %s.", scopeAnnotation); } public Errors scopeAnnotationOnAbstractType( Class scopeAnnotation, Class type, Object source) { return addMessage("%s is annotated with %s, but scope annotations are not supported " + "for abstract types.%n Bound at %s.", type, scopeAnnotation, convert(source)); } public Errors misplacedBindingAnnotation(Member member, Annotation bindingAnnotation) { return addMessage("%s is annotated with %s, but binding annotations should be applied " + "to its parameters instead.", member, bindingAnnotation); } private static final String CONSTRUCTOR_RULES = "Classes must have either one (and only one) constructor " + "annotated with @Inject or a zero-argument constructor that is not private."; public Errors missingConstructor(Class implementation) { return addMessage("Could not find a suitable constructor in %s. " + CONSTRUCTOR_RULES, implementation); } public Errors tooManyConstructors(Class implementation) { return addMessage("%s has more than one constructor annotated with @Inject. " + CONSTRUCTOR_RULES, implementation); } public Errors constructorNotDefinedByType(Constructor constructor, TypeLiteral type) { return addMessage("%s does not define %s", type, constructor); } public Errors duplicateScopes(Scope existing, Class annotationType, Scope scope) { return addMessage("Scope %s is already bound to %s. Cannot bind %s.", existing, annotationType, scope); } public Errors voidProviderMethod() { return addMessage("Provider methods must return a value. Do not return void."); } public Errors missingConstantValues() { return addMessage("Missing constant value. Please call to(...)."); } public Errors cannotInjectInnerClass(Class type) { return addMessage("Injecting into inner classes is not supported. " + "Please use a 'static' class (top-level or nested) instead of %s.", type); } public Errors duplicateBindingAnnotations(Member member, Class a, Class b) { return addMessage("%s has more than one annotation annotated with @BindingAnnotation: " + "%s and %s", member, a, b); } public Errors cannotInjectFinalField(Field field) { return addMessage("Injected field %s cannot be final.", field); } public Errors cannotInjectAbstractMethod(Method method) { return addMessage("Injected method %s cannot be abstract.", method); } public Errors cannotInjectNonVoidMethod(Method method) { return addMessage("Injected method %s must return void.", method); } public Errors cannotInjectMethodWithTypeParameters(Method method) { return addMessage("Injected method %s cannot declare type parameters of its own.", method); } public Errors duplicateScopeAnnotations( Class a, Class b) { return addMessage("More than one scope annotation was found: %s and %s.", a, b); } public Errors recursiveBinding() { return addMessage("Binding points to itself."); } public Errors bindingAlreadySet(Key key, Object source) { return addMessage("A binding to %s was already configured at %s.", key, convert(source)); } public Errors jitBindingAlreadySet(Key key) { return addMessage("A just-in-time binding to %s was already configured on a parent injector.", key); } public Errors childBindingAlreadySet(Key key, Set sources) { Formatter allSources = new Formatter(); for (Object source : sources) { if (source == null) { allSources.format("%n (bound by a just-in-time binding)"); } else { allSources.format("%n bound at %s", source); } } Errors errors = addMessage( "Unable to create binding for %s." + " It was already configured on one or more child injectors or private modules" + "%s%n" + " If it was in a PrivateModule, did you forget to expose the binding?", key, allSources.out()); return errors; } public Errors errorCheckingDuplicateBinding(Key key, Object source, Throwable t) { return addMessage( "A binding to %s was already configured at %s and an error was thrown " + "while checking duplicate bindings. Error: %s", key, convert(source), t); } public Errors errorInjectingMethod(Throwable cause) { return errorInUserCode(cause, "Error injecting method, %s", cause); } public Errors errorNotifyingTypeListener(TypeListenerBinding listener, TypeLiteral type, Throwable cause) { return errorInUserCode(cause, "Error notifying TypeListener %s (bound at %s) of %s.%n" + " Reason: %s", listener.getListener(), convert(listener.getSource()), type, cause); } public Errors errorInjectingConstructor(Throwable cause) { return errorInUserCode(cause, "Error injecting constructor, %s", cause); } public Errors errorInProvider(RuntimeException runtimeException) { Throwable unwrapped = unwrap(runtimeException); return errorInUserCode(unwrapped, "Error in custom provider, %s", unwrapped); } public Errors errorInUserInjector( MembersInjector listener, TypeLiteral type, RuntimeException cause) { return errorInUserCode(cause, "Error injecting %s using %s.%n" + " Reason: %s", type, listener, cause); } public Errors errorNotifyingInjectionListener( InjectionListener listener, TypeLiteral type, RuntimeException cause) { return errorInUserCode(cause, "Error notifying InjectionListener %s of %s.%n" + " Reason: %s", listener, type, cause); } public Errors exposedButNotBound(Key key) { return addMessage("Could not expose() %s, it must be explicitly bound.", key); } public Errors keyNotFullySpecified(TypeLiteral typeLiteral) { return addMessage("%s cannot be used as a key; It is not fully specified.", typeLiteral); } public Errors errorEnhancingClass(Class clazz, Throwable cause) { return errorInUserCode(cause, "Unable to method intercept: %s", clazz); } public static Collection getMessagesFromThrowable(Throwable throwable) { if (throwable instanceof ProvisionException) { return ((ProvisionException) throwable).getErrorMessages(); } else if (throwable instanceof ConfigurationException) { return ((ConfigurationException) throwable).getErrorMessages(); } else if (throwable instanceof CreationException) { return ((CreationException) throwable).getErrorMessages(); } else { return ImmutableSet.of(); } } public Errors errorInUserCode(Throwable cause, String messageFormat, Object... arguments) { Collection messages = getMessagesFromThrowable(cause); if (!messages.isEmpty()) { return merge(messages); } else { return addMessage(cause, messageFormat, arguments); } } private Throwable unwrap(RuntimeException runtimeException) { if(runtimeException instanceof Exceptions.UnhandledCheckedUserException) { return runtimeException.getCause(); } else { return runtimeException; } } public Errors cannotInjectRawProvider() { return addMessage("Cannot inject a Provider that has no type parameter"); } public Errors cannotInjectRawMembersInjector() { return addMessage("Cannot inject a MembersInjector that has no type parameter"); } public Errors cannotInjectTypeLiteralOf(Type unsupportedType) { return addMessage("Cannot inject a TypeLiteral of %s", unsupportedType); } public Errors cannotInjectRawTypeLiteral() { return addMessage("Cannot inject a TypeLiteral that has no type parameter"); } public Errors cannotSatisfyCircularDependency(Class expectedType) { return addMessage( "Tried proxying %s to support a circular dependency, but it is not an interface.", expectedType); } public Errors circularProxiesDisabled(Class expectedType) { return addMessage( "Tried proxying %s to support a circular dependency, but circular proxies are disabled.", expectedType); } public void throwCreationExceptionIfErrorsExist() { if (!hasErrors()) { return; } throw new CreationException(getMessages()); } public void throwConfigurationExceptionIfErrorsExist() { if (!hasErrors()) { return; } throw new ConfigurationException(getMessages()); } public void throwProvisionExceptionIfErrorsExist() { if (!hasErrors()) { return; } throw new ProvisionException(getMessages()); } private Message merge(Message message) { List sources = Lists.newArrayList(); sources.addAll(getSources()); sources.addAll(message.getSources()); return new Message(sources, message.getMessage(), message.getCause()); } public Errors merge(Collection messages) { for (Message message : messages) { addMessage(merge(message)); } return this; } public Errors merge(Errors moreErrors) { if (moreErrors.root == root || moreErrors.root.errors == null) { return this; } merge(moreErrors.root.errors); return this; } public List getSources() { List sources = Lists.newArrayList(); for (Errors e = this; e != null; e = e.parent) { if (e.source != SourceProvider.UNKNOWN_SOURCE) { sources.add(0, e.source); } } return sources; } public void throwIfNewErrors(int expectedSize) throws ErrorsException { if (size() == expectedSize) { return; } throw toException(); } public ErrorsException toException() { return new ErrorsException(this); } public boolean hasErrors() { return root.errors != null; } public Errors addMessage(String messageFormat, Object... arguments) { return addMessage(null, messageFormat, arguments); } private Errors addMessage(Throwable cause, String messageFormat, Object... arguments) { String message = format(messageFormat, arguments); addMessage(new Message(getSources(), message, cause)); return this; } public Errors addMessage(Message message) { if (root.errors == null) { root.errors = Lists.newArrayList(); } root.errors.add(message); return this; } public static String format(String messageFormat, Object... arguments) { for (int i = 0; i < arguments.length; i++) { arguments[i] = Errors.convert(arguments[i]); } return String.format(messageFormat, arguments); } public List getMessages() { if (root.errors == null) { return ImmutableList.of(); } List result = Lists.newArrayList(root.errors); Collections.sort(result, new Comparator() { public int compare(Message a, Message b) { return a.getSource().compareTo(b.getSource()); } }); return result; } /** Returns the formatted message for an exception with the specified messages. */ public static String format(String heading, Collection errorMessages) { Formatter fmt = new Formatter().format(heading).format(":%n%n"); int index = 1; boolean displayCauses = getOnlyCause(errorMessages) == null; for (Message errorMessage : errorMessages) { fmt.format("%s) %s%n", index++, errorMessage.getMessage()); List dependencies = errorMessage.getSources(); for (int i = dependencies.size() - 1; i >= 0; i--) { Object source = dependencies.get(i); formatSource(fmt, source); } Throwable cause = errorMessage.getCause(); if (displayCauses && cause != null) { StringWriter writer = new StringWriter(); cause.printStackTrace(new PrintWriter(writer)); fmt.format("Caused by: %s", writer.getBuffer()); } fmt.format("%n"); } if (errorMessages.size() == 1) { fmt.format("1 error"); } else { fmt.format("%s errors", errorMessages.size()); } return fmt.toString(); } /** * Returns {@code value} if it is non-null allowed to be null. Otherwise a message is added and * an {@code ErrorsException} is thrown. */ public T checkForNull(T value, Object source, Dependency dependency) throws ErrorsException { if (value != null || dependency.isNullable()) { return value; } int parameterIndex = dependency.getParameterIndex(); String parameterName = (parameterIndex != -1) ? "parameter " + parameterIndex + " of " : ""; addMessage("null returned by binding at %s%n but %s%s is not @Nullable", source, parameterName, dependency.getInjectionPoint().getMember()); throw toException(); } /** * Returns the cause throwable if there is exactly one cause in {@code messages}. If there are * zero or multiple messages with causes, null is returned. */ public static Throwable getOnlyCause(Collection messages) { Throwable onlyCause = null; for (Message message : messages) { Throwable messageCause = message.getCause(); if (messageCause == null) { continue; } if (onlyCause != null) { return null; } onlyCause = messageCause; } return onlyCause; } public int size() { return root.errors == null ? 0 : root.errors.size(); } private static abstract class Converter { final Class type; Converter(Class type) { this.type = type; } boolean appliesTo(Object o) { return o != null && type.isAssignableFrom(o.getClass()); } String convert(Object o) { return toString(type.cast(o)); } abstract String toString(T t); } private static final Collection> converters = ImmutableList.of( new Converter(Class.class) { public String toString(Class c) { return c.getName(); } }, new Converter(Member.class) { public String toString(Member member) { return Classes.toString(member); } }, new Converter(Key.class) { public String toString(Key key) { if (key.getAnnotationType() != null) { return key.getTypeLiteral() + " annotated with " + (key.getAnnotation() != null ? key.getAnnotation() : key.getAnnotationType()); } else { return key.getTypeLiteral().toString(); } } }); public static Object convert(Object o) { for (Converter converter : converters) { if (converter.appliesTo(o)) { return converter.convert(o); } } return o; } public static void formatSource(Formatter formatter, Object source) { if (source instanceof Dependency) { Dependency dependency = (Dependency) source; InjectionPoint injectionPoint = dependency.getInjectionPoint(); if (injectionPoint != null) { formatInjectionPoint(formatter, dependency, injectionPoint); } else { formatSource(formatter, dependency.getKey()); } } else if (source instanceof InjectionPoint) { formatInjectionPoint(formatter, null, (InjectionPoint) source); } else if (source instanceof Class) { formatter.format(" at %s%n", StackTraceElements.forType((Class) source)); } else if (source instanceof Member) { formatter.format(" at %s%n", StackTraceElements.forMember((Member) source)); } else if (source instanceof TypeLiteral) { formatter.format(" while locating %s%n", source); } else if (source instanceof Key) { Key key = (Key) source; formatter.format(" while locating %s%n", convert(key)); } else { formatter.format(" at %s%n", source); } } public static void formatInjectionPoint(Formatter formatter, Dependency dependency, InjectionPoint injectionPoint) { Member member = injectionPoint.getMember(); Class memberType = Classes.memberType(member); if (memberType == Field.class) { dependency = injectionPoint.getDependencies().get(0); formatter.format(" while locating %s%n", convert(dependency.getKey())); formatter.format(" for field at %s%n", StackTraceElements.forMember(member)); } else if (dependency != null) { formatter.format(" while locating %s%n", convert(dependency.getKey())); formatter.format(" for parameter %s at %s%n", dependency.getParameterIndex(), StackTraceElements.forMember(member)); } else { formatSource(formatter, injectionPoint.getMember()); } } } guice-3.0/core/src/com/google/inject/internal/InjectorShell.java0000644000175000017500000002314011536235744024627 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import static com.google.inject.Scopes.SINGLETON; import com.google.inject.Singleton; import com.google.inject.Stage; import com.google.inject.internal.InjectorImpl.InjectorOptions; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import static com.google.inject.internal.util.Preconditions.checkNotNull; import static com.google.inject.internal.util.Preconditions.checkState; import com.google.inject.internal.util.SourceProvider; import com.google.inject.internal.util.Stopwatch; import com.google.inject.spi.Dependency; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.PrivateElements; import com.google.inject.spi.TypeListenerBinding; import java.util.List; import java.util.logging.Logger; /** * A partially-initialized injector. See {@link InternalInjectorCreator}, which * uses this to build a tree of injectors in batch. * * @author jessewilson@google.com (Jesse Wilson) */ final class InjectorShell { private final List elements; private final InjectorImpl injector; private InjectorShell(Builder builder, List elements, InjectorImpl injector) { this.elements = elements; this.injector = injector; } InjectorImpl getInjector() { return injector; } List getElements() { return elements; } static class Builder { private final List elements = Lists.newArrayList(); private final List modules = Lists.newArrayList(); /** lazily constructed */ private State state; private InjectorImpl parent; private InjectorOptions options; private Stage stage; /** null unless this exists in a {@link Binder#newPrivateBinder private environment} */ private PrivateElementsImpl privateElements; Builder stage(Stage stage) { this.stage = stage; return this; } Builder parent(InjectorImpl parent) { this.parent = parent; this.state = new InheritingState(parent.state); this.options = parent.options; this.stage = options.stage; return this; } Builder privateElements(PrivateElements privateElements) { this.privateElements = (PrivateElementsImpl) privateElements; this.elements.addAll(privateElements.getElements()); return this; } void addModules(Iterable modules) { for (Module module : modules) { this.modules.add(module); } } Stage getStage() { return options.stage; } /** Synchronize on this before calling {@link #build}. */ Object lock() { return getState().lock(); } /** * Creates and returns the injector shells for the current modules. Multiple shells will be * returned if any modules contain {@link Binder#newPrivateBinder private environments}. The * primary injector will be first in the returned list. */ List build( Initializer initializer, ProcessedBindingData bindingData, Stopwatch stopwatch, Errors errors) { checkState(stage != null, "Stage not initialized"); checkState(privateElements == null || parent != null, "PrivateElements with no parent"); checkState(state != null, "no state. Did you remember to lock() ?"); // bind Stage and Singleton if this is a top-level injector if (parent == null) { modules.add(0, new RootModule(stage)); } elements.addAll(Elements.getElements(stage, modules)); // Look for injector-changing options InjectorOptionsProcessor optionsProcessor = new InjectorOptionsProcessor(errors); optionsProcessor.process(null, elements); options = optionsProcessor.getOptions(stage, options); InjectorImpl injector = new InjectorImpl(parent, state, options); if (privateElements != null) { privateElements.initInjector(injector); } // add default type converters if this is a top-level injector if (parent == null) { new TypeConverterBindingProcessor(errors).prepareBuiltInConverters(injector); } stopwatch.resetAndLog("Module execution"); new MessageProcessor(errors).process(injector, elements); /*if[AOP]*/ InterceptorBindingProcessor interceptors = new InterceptorBindingProcessor(errors); interceptors.process(injector, elements); stopwatch.resetAndLog("Interceptors creation"); /*end[AOP]*/ new TypeListenerBindingProcessor(errors).process(injector, elements); List listenerBindings = injector.state.getTypeListenerBindings(); injector.membersInjectorStore = new MembersInjectorStore(injector, listenerBindings); stopwatch.resetAndLog("TypeListeners creation"); new ScopeBindingProcessor(errors).process(injector, elements); stopwatch.resetAndLog("Scopes creation"); new TypeConverterBindingProcessor(errors).process(injector, elements); stopwatch.resetAndLog("Converters creation"); bindInjector(injector); bindLogger(injector); // Process all normal bindings, then UntargettedBindings. // This is necessary because UntargettedBindings can create JIT bindings // and need all their other dependencies set up ahead of time. new BindingProcessor(errors, initializer, bindingData).process(injector, elements); new UntargettedBindingProcessor(errors, bindingData).process(injector, elements); stopwatch.resetAndLog("Binding creation"); List injectorShells = Lists.newArrayList(); injectorShells.add(new InjectorShell(this, elements, injector)); // recursively build child shells PrivateElementProcessor processor = new PrivateElementProcessor(errors); processor.process(injector, elements); for (Builder builder : processor.getInjectorShellBuilders()) { injectorShells.addAll(builder.build(initializer, bindingData, stopwatch, errors)); } stopwatch.resetAndLog("Private environment creation"); return injectorShells; } private State getState() { if (state == null) { state = new InheritingState(State.NONE); } return state; } } /** * The Injector is a special case because we allow both parent and child injectors to both have * a binding for that key. */ private static void bindInjector(InjectorImpl injector) { Key key = Key.get(Injector.class); InjectorFactory injectorFactory = new InjectorFactory(injector); injector.state.putBinding(key, new ProviderInstanceBindingImpl(injector, key, SourceProvider.UNKNOWN_SOURCE, injectorFactory, Scoping.UNSCOPED, injectorFactory, ImmutableSet.of())); } private static class InjectorFactory implements InternalFactory, Provider { private final Injector injector; private InjectorFactory(Injector injector) { this.injector = injector; } public Injector get(Errors errors, InternalContext context, Dependency dependency, boolean linked) throws ErrorsException { return injector; } public Injector get() { return injector; } public String toString() { return "Provider"; } } /** * The Logger is a special case because it knows the injection point of the injected member. It's * the only binding that does this. */ private static void bindLogger(InjectorImpl injector) { Key key = Key.get(Logger.class); LoggerFactory loggerFactory = new LoggerFactory(); injector.state.putBinding(key, new ProviderInstanceBindingImpl(injector, key, SourceProvider.UNKNOWN_SOURCE, loggerFactory, Scoping.UNSCOPED, loggerFactory, ImmutableSet.of())); } private static class LoggerFactory implements InternalFactory, Provider { public Logger get(Errors errors, InternalContext context, Dependency dependency, boolean linked) { InjectionPoint injectionPoint = dependency.getInjectionPoint(); return injectionPoint == null ? Logger.getAnonymousLogger() : Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName()); } public Logger get() { return Logger.getAnonymousLogger(); } public String toString() { return "Provider"; } } private static class RootModule implements Module { final Stage stage; private RootModule(Stage stage) { this.stage = checkNotNull(stage, "stage"); } public void configure(Binder binder) { binder = binder.withSource(SourceProvider.UNKNOWN_SOURCE); binder.bind(Stage.class).toInstance(stage); binder.bindScope(Singleton.class, SINGLETON); binder.bindScope(javax.inject.Singleton.class, SINGLETON); } } } guice-3.0/core/src/com/google/inject/internal/MessageProcessor.java0000644000175000017500000000313011460133000025315 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Guice; import com.google.inject.spi.Message; import java.util.logging.Level; import java.util.logging.Logger; /** * Handles {@code Binder.addError} commands. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ final class MessageProcessor extends AbstractProcessor { private static final Logger logger = Logger.getLogger(Guice.class.getName()); MessageProcessor(Errors errors) { super(errors); } @Override public Boolean visit(Message message) { if (message.getCause() != null) { String rootMessage = getRootMessage(message.getCause()); logger.log(Level.INFO, "An exception was caught and reported. Message: " + rootMessage, message.getCause()); } errors.addMessage(message); return true; } public static String getRootMessage(Throwable t) { Throwable cause = t.getCause(); return cause == null ? t.toString() : getRootMessage(cause); } } guice-3.0/core/src/com/google/inject/internal/Annotations.java0000644000175000017500000001613711502212010024335 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.BindingAnnotation; import com.google.inject.Key; import com.google.inject.ScopeAnnotation; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Classes; import com.google.inject.internal.util.Function; import com.google.inject.internal.util.MapMaker; import com.google.inject.name.Named; import com.google.inject.name.Names; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Member; import java.util.Arrays; import java.util.Collection; import java.util.Map; import javax.inject.Qualifier; /** * Annotation utilities. * * @author crazybob@google.com (Bob Lee) */ public class Annotations { /** * Returns {@code true} if the given annotation type has no attributes. */ public static boolean isMarker(Class annotationType) { return annotationType.getDeclaredMethods().length == 0; } /** * Returns true if the given annotation is retained at runtime. */ public static boolean isRetainedAtRuntime(Class annotationType) { Retention retention = annotationType.getAnnotation(Retention.class); return retention != null && retention.value() == RetentionPolicy.RUNTIME; } /** Returns the scope annotation on {@code type}, or null if none is specified. */ public static Class findScopeAnnotation( Errors errors, Class implementation) { return findScopeAnnotation(errors, implementation.getAnnotations()); } /** Returns the scoping annotation, or null if there isn't one. */ public static Class findScopeAnnotation(Errors errors, Annotation[] annotations) { Class found = null; for (Annotation annotation : annotations) { Class annotationType = annotation.annotationType(); if (isScopeAnnotation(annotationType)) { if (found != null) { errors.duplicateScopeAnnotations(found, annotationType); } else { found = annotationType; } } } return found; } /** * Checks for the presence of annotations. Caches results because Android doesn't. */ static class AnnotationChecker { private final Collection> annotationTypes; /** Returns true if the given class has one of the desired annotations. */ private Function, Boolean> hasAnnotations = new Function, Boolean>() { public Boolean apply(Class annotationType) { for (Annotation annotation : annotationType.getAnnotations()) { if (annotationTypes.contains(annotation.annotationType())) { return true; } } return false; } }; final Map, Boolean> cache = new MapMaker().weakKeys() .makeComputingMap(hasAnnotations); /** * Constructs a new checker that looks for annotations of the given types. */ AnnotationChecker(Collection> annotationTypes) { this.annotationTypes = annotationTypes; } /** * Returns true if the given type has one of the desired annotations. */ boolean hasAnnotations(Class annotated) { return cache.get(annotated); } } private static final AnnotationChecker scopeChecker = new AnnotationChecker( Arrays.asList(ScopeAnnotation.class, javax.inject.Scope.class)); public static boolean isScopeAnnotation(Class annotationType) { return scopeChecker.hasAnnotations(annotationType); } /** * Adds an error if there is a misplaced annotations on {@code type}. Scoping * annotations are not allowed on abstract classes or interfaces. */ public static void checkForMisplacedScopeAnnotations( Class type, Object source, Errors errors) { if (Classes.isConcrete(type)) { return; } Class scopeAnnotation = findScopeAnnotation(errors, type); if (scopeAnnotation != null) { errors.withSource(type).scopeAnnotationOnAbstractType(scopeAnnotation, type, source); } } /** Gets a key for the given type, member and annotations. */ public static Key getKey(TypeLiteral type, Member member, Annotation[] annotations, Errors errors) throws ErrorsException { int numErrorsBefore = errors.size(); Annotation found = findBindingAnnotation(errors, member, annotations); errors.throwIfNewErrors(numErrorsBefore); return found == null ? Key.get(type) : Key.get(type, found); } /** * Returns the binding annotation on {@code member}, or null if there isn't one. */ public static Annotation findBindingAnnotation( Errors errors, Member member, Annotation[] annotations) { Annotation found = null; for (Annotation annotation : annotations) { Class annotationType = annotation.annotationType(); if (isBindingAnnotation(annotationType)) { if (found != null) { errors.duplicateBindingAnnotations(member, found.annotationType(), annotationType); } else { found = annotation; } } } return found; } private static final AnnotationChecker bindingAnnotationChecker = new AnnotationChecker( Arrays.asList(BindingAnnotation.class, Qualifier.class)); /** * Returns true if annotations of the specified type are binding annotations. */ public static boolean isBindingAnnotation(Class annotationType) { return bindingAnnotationChecker.hasAnnotations(annotationType); } /** * If the annotation is an instance of {@code javax.inject.Named}, canonicalizes to * com.google.guice.name.Named. Returns the given annotation otherwise. */ public static Annotation canonicalizeIfNamed(Annotation annotation) { if(annotation instanceof javax.inject.Named) { return Names.named(((javax.inject.Named)annotation).value()); } else { return annotation; } } /** * If the annotation is the class {@code javax.inject.Named}, canonicalizes to * com.google.guice.name.Named. Returns the given annotation class otherwise. */ public static Class canonicalizeIfNamed( Class annotationType) { if (annotationType == javax.inject.Named.class) { return Named.class; } else { return annotationType; } } } guice-3.0/core/src/com/google/inject/internal/PrivateElementProcessor.java0000644000175000017500000000266111501171754026703 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.util.Lists; import com.google.inject.spi.PrivateElements; import java.util.List; /** * Handles {@code Binder.newPrivateBinder()} elements. * * @author jessewilson@google.com (Jesse Wilson) */ final class PrivateElementProcessor extends AbstractProcessor { private final List injectorShellBuilders = Lists.newArrayList(); PrivateElementProcessor(Errors errors) { super(errors); } @Override public Boolean visit(PrivateElements privateElements) { InjectorShell.Builder builder = new InjectorShell.Builder() .parent(injector) .privateElements(privateElements); injectorShellBuilders.add(builder); return true; } public List getInjectorShellBuilders() { return injectorShellBuilders; } } guice-3.0/core/src/com/google/inject/internal/TypeConverterBindingProcessor.java0000644000175000017500000001327311471305404030061 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.SourceProvider; import com.google.inject.internal.util.Strings; import com.google.inject.matcher.AbstractMatcher; import com.google.inject.matcher.Matcher; import com.google.inject.matcher.Matchers; import com.google.inject.spi.TypeConverter; import com.google.inject.spi.TypeConverterBinding; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; /** * Handles {@code Binder.convertToTypes} commands. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ final class TypeConverterBindingProcessor extends AbstractProcessor { TypeConverterBindingProcessor(Errors errors) { super(errors); } /** Installs default converters for primitives, enums, and class literals. */ void prepareBuiltInConverters(InjectorImpl injector) { this.injector = injector; try { // Configure type converters. convertToPrimitiveType(int.class, Integer.class); convertToPrimitiveType(long.class, Long.class); convertToPrimitiveType(boolean.class, Boolean.class); convertToPrimitiveType(byte.class, Byte.class); convertToPrimitiveType(short.class, Short.class); convertToPrimitiveType(float.class, Float.class); convertToPrimitiveType(double.class, Double.class); convertToClass(Character.class, new TypeConverter() { public Object convert(String value, TypeLiteral toType) { value = value.trim(); if (value.length() != 1) { throw new RuntimeException("Length != 1."); } return value.charAt(0); } @Override public String toString() { return "TypeConverter"; } }); convertToClasses(Matchers.subclassesOf(Enum.class), new TypeConverter() { @SuppressWarnings("unchecked") public Object convert(String value, TypeLiteral toType) { return Enum.valueOf((Class) toType.getRawType(), value); } @Override public String toString() { return "TypeConverter>"; } }); internalConvertToTypes( new AbstractMatcher>() { public boolean matches(TypeLiteral typeLiteral) { return typeLiteral.getRawType() == Class.class; } @Override public String toString() { return "Class"; } }, new TypeConverter() { @SuppressWarnings("unchecked") public Object convert(String value, TypeLiteral toType) { try { return Class.forName(value); } catch (ClassNotFoundException e) { throw new RuntimeException(e.getMessage()); } } @Override public String toString() { return "TypeConverter>"; } } ); } finally { this.injector = null; } } private void convertToPrimitiveType(Class primitiveType, final Class wrapperType) { try { final Method parser = wrapperType.getMethod( "parse" + Strings.capitalize(primitiveType.getName()), String.class); TypeConverter typeConverter = new TypeConverter() { @SuppressWarnings("unchecked") public Object convert(String value, TypeLiteral toType) { try { return parser.invoke(null, value); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new RuntimeException(e.getTargetException().getMessage()); } } @Override public String toString() { return "TypeConverter<" + wrapperType.getSimpleName() + ">"; } }; convertToClass(wrapperType, typeConverter); } catch (NoSuchMethodException e) { throw new AssertionError(e); } } private void convertToClass(Class type, TypeConverter converter) { convertToClasses(Matchers.identicalTo(type), converter); } private void convertToClasses(final Matcher> typeMatcher, TypeConverter converter) { internalConvertToTypes(new AbstractMatcher>() { public boolean matches(TypeLiteral typeLiteral) { Type type = typeLiteral.getType(); if (!(type instanceof Class)) { return false; } Class clazz = (Class) type; return typeMatcher.matches(clazz); } @Override public String toString() { return typeMatcher.toString(); } }, converter); } private void internalConvertToTypes(Matcher> typeMatcher, TypeConverter converter) { injector.state.addConverter( new TypeConverterBinding(SourceProvider.UNKNOWN_SOURCE, typeMatcher, converter)); } @Override public Boolean visit(TypeConverterBinding command) { injector.state.addConverter(new TypeConverterBinding( command.getSource(), command.getTypeMatcher(), command.getTypeConverter())); return true; } } guice-3.0/core/src/com/google/inject/internal/CircularDependencyProxy.java0000644000175000017500000000136611460133000026647 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; /** * @author jessewilson@google.com (Jesse Wilson) */ public interface CircularDependencyProxy { // marker interface } guice-3.0/core/src/com/google/inject/internal/InternalContext.java0000644000175000017500000000322311460135342025170 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.util.Maps; import com.google.inject.spi.Dependency; import java.util.Map; /** * Internal context. Used to coordinate injections and support circular * dependencies. * * @author crazybob@google.com (Bob Lee) */ final class InternalContext { private Map> constructionContexts = Maps.newHashMap(); private Dependency dependency; @SuppressWarnings("unchecked") public ConstructionContext getConstructionContext(Object key) { ConstructionContext constructionContext = (ConstructionContext) constructionContexts.get(key); if (constructionContext == null) { constructionContext = new ConstructionContext(); constructionContexts.put(key, constructionContext); } return constructionContext; } public Dependency getDependency() { return dependency; } public Dependency setDependency(Dependency dependency) { Dependency previous = this.dependency; this.dependency = dependency; return previous; } } guice-3.0/core/src/com/google/inject/internal/InjectorOptionsProcessor.java0000644000175000017500000000420511501622276027104 0ustar drazzibdrazzib/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import static com.google.inject.internal.util.Preconditions.checkNotNull; import static com.google.inject.internal.util.Preconditions.checkState; import com.google.inject.Stage; import com.google.inject.internal.InjectorImpl.InjectorOptions; import com.google.inject.spi.DisableCircularProxiesOption; import com.google.inject.spi.RequireExplicitBindingsOption; /** * A processor to gather injector options. * * @author sameb@google.com (Sam Berlin) */ class InjectorOptionsProcessor extends AbstractProcessor { private boolean disableCircularProxies = false; private boolean jitDisabled = false; InjectorOptionsProcessor(Errors errors) { super(errors); } @Override public Boolean visit(DisableCircularProxiesOption option) { disableCircularProxies = true; return true; } @Override public Boolean visit(RequireExplicitBindingsOption option) { jitDisabled = true; return true; } InjectorOptions getOptions(Stage stage, InjectorOptions parentOptions) { checkNotNull(stage, "stage must be set"); if(parentOptions == null) { return new InjectorOptions( stage, jitDisabled, disableCircularProxies); } else { checkState(stage == parentOptions.stage, "child & parent stage don't match"); return new InjectorOptions( stage, jitDisabled || parentOptions.jitDisabled, disableCircularProxies || parentOptions.disableCircularProxies); } } } guice-3.0/core/src/com/google/inject/internal/WeakKeySet.java0000644000175000017500000000443311532237654024100 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Key; import com.google.inject.internal.util.Maps; import com.google.inject.internal.util.Sets; import com.google.inject.internal.util.SourceProvider; import java.util.Map; import java.util.Set; /** * Minimal set that doesn't hold strong references to the contained keys. * * @author jessewilson@google.com (Jesse Wilson) */ final class WeakKeySet { /** * We store strings rather than keys so we don't hold strong references. * *

One potential problem with this approach is that parent and child injectors cannot define * keys whose class names are equal but class loaders are different. This shouldn't be an issue * in practice. */ private Map> backingSet; public void add(Key key, Object source) { if (backingSet == null) { backingSet = Maps.newHashMap(); } // if it's an instanceof Class, it was a JIT binding, which we don't // want to retain. if (source instanceof Class || source == SourceProvider.UNKNOWN_SOURCE) { source = null; } String k = key.toString(); Set sources = backingSet.get(k); if (sources == null) { sources = Sets.newLinkedHashSet(); backingSet.put(k, sources); } sources.add(Errors.convert(source)); } public boolean contains(Key key) { // avoid calling key.toString() if the backing set is empty. toString is expensive in aggregate, // and most WeakKeySets are empty in practice (because they're used by top-level injectors) return backingSet != null && backingSet.containsKey(key.toString()); } public Set getSources(Key key) { return backingSet.get(key.toString()); } } guice-3.0/core/src/com/google/inject/internal/ConstructorInjector.java0000644000175000017500000000750511460133000026066 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.spi.InjectionPoint; import java.lang.reflect.InvocationTargetException; import java.util.Set; /** * Creates instances using an injectable constructor. After construction, all injectable fields and * methods are injected. * * @author crazybob@google.com (Bob Lee) */ final class ConstructorInjector { private final ImmutableSet injectableMembers; private final SingleParameterInjector[] parameterInjectors; private final ConstructionProxy constructionProxy; private final MembersInjectorImpl membersInjector; ConstructorInjector(Set injectableMembers, ConstructionProxy constructionProxy, SingleParameterInjector[] parameterInjectors, MembersInjectorImpl membersInjector) { this.injectableMembers = ImmutableSet.copyOf(injectableMembers); this.constructionProxy = constructionProxy; this.parameterInjectors = parameterInjectors; this.membersInjector = membersInjector; } public ImmutableSet getInjectableMembers() { return injectableMembers; } ConstructionProxy getConstructionProxy() { return constructionProxy; } /** * Construct an instance. Returns {@code Object} instead of {@code T} because * it may return a proxy. */ Object construct(Errors errors, InternalContext context, Class expectedType, boolean allowProxy) throws ErrorsException { ConstructionContext constructionContext = context.getConstructionContext(this); // We have a circular reference between constructors. Return a proxy. if (constructionContext.isConstructing()) { if(!allowProxy) { throw errors.circularProxiesDisabled(expectedType).toException(); } else { // TODO (crazybob): if we can't proxy this object, can we proxy the other object? return constructionContext.createProxy(errors, expectedType); } } // If we're re-entering this factory while injecting fields or methods, // return the same instance. This prevents infinite loops. T t = constructionContext.getCurrentReference(); if (t != null) { return t; } try { // First time through... constructionContext.startConstruction(); try { Object[] parameters = SingleParameterInjector.getAll(errors, context, parameterInjectors); t = constructionProxy.newInstance(parameters); constructionContext.setProxyDelegates(t); } finally { constructionContext.finishConstruction(); } // Store reference. If an injector re-enters this factory, they'll get the same reference. constructionContext.setCurrentReference(t); membersInjector.injectMembers(t, errors, context, false); membersInjector.notifyListeners(t, errors); return t; } catch (InvocationTargetException userException) { Throwable cause = userException.getCause() != null ? userException.getCause() : userException; throw errors.withSource(constructionProxy.getInjectionPoint()) .errorInjectingConstructor(cause).toException(); } finally { constructionContext.removeCurrentReference(); } } } guice-3.0/core/src/com/google/inject/internal/ExposedBindingImpl.java0000644000175000017500000000444111460133000025563 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.ExposedBinding; import com.google.inject.spi.PrivateElements; import java.util.Set; public final class ExposedBindingImpl extends BindingImpl implements ExposedBinding { private final PrivateElements privateElements; public ExposedBindingImpl(InjectorImpl injector, Object source, Key key, InternalFactory factory, PrivateElements privateElements) { super(injector, key, source, factory, Scoping.UNSCOPED); this.privateElements = privateElements; } public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(Key.get(Injector.class))); } public PrivateElements getPrivateElements() { return privateElements; } @Override public String toString() { return new ToStringBuilder(ExposedBinding.class) .add("key", getKey()) .add("source", getSource()) .add("privateElements", privateElements) .toString(); } public void applyTo(Binder binder) { throw new UnsupportedOperationException("This element represents a synthetic binding."); } // Purposely does not override equals/hashcode, because exposed bindings are only equal to // themselves right now -- that is, there cannot be "duplicate" exposed bindings. } guice-3.0/core/src/com/google/inject/internal/InternalInjectorCreator.java0000644000175000017500000002662311536234470026660 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binding; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.MembersInjector; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.Stage; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Iterables; import com.google.inject.internal.util.Stopwatch; import com.google.inject.spi.Dependency; import com.google.inject.spi.TypeConverterBinding; import java.lang.annotation.Annotation; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; /** * Builds a tree of injectors. This is a primary injector, plus child injectors needed for each * {@code Binder.newPrivateBinder() private environment}. The primary injector is not necessarily a * top-level injector. * *

Injector construction happens in two phases. *

    *
  1. Static building. In this phase, we interpret commands, create bindings, and inspect * dependencies. During this phase, we hold a lock to ensure consistency with parent injectors. * No user code is executed in this phase.
  2. *
  3. Dynamic injection. In this phase, we call user code. We inject members that requested * injection. This may require user's objects be created and their providers be called. And we * create eager singletons. In this phase, user code may have started other threads. This phase * is not executed for injectors created using {@link Stage#TOOL the tool stage}
  4. *
* * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ public final class InternalInjectorCreator { private final Stopwatch stopwatch = new Stopwatch(); private final Errors errors = new Errors(); private final Initializer initializer = new Initializer(); private final ProcessedBindingData bindingData; private final InjectionRequestProcessor injectionRequestProcessor; private final InjectorShell.Builder shellBuilder = new InjectorShell.Builder(); private List shells; public InternalInjectorCreator() { injectionRequestProcessor = new InjectionRequestProcessor(errors, initializer); bindingData = new ProcessedBindingData(); } public InternalInjectorCreator stage(Stage stage) { shellBuilder.stage(stage); return this; } /** * Sets the parent of the injector to-be-constructed. As a side effect, this sets this injector's * stage to the stage of {@code parent} and sets {@link #requireExplicitBindings()} if the parent * injector also required them. */ public InternalInjectorCreator parentInjector(InjectorImpl parent) { shellBuilder.parent(parent); return this; } public InternalInjectorCreator addModules(Iterable modules) { shellBuilder.addModules(modules); return this; } public Injector build() { if (shellBuilder == null) { throw new AssertionError("Already built, builders are not reusable."); } // Synchronize while we're building up the bindings and other injector state. This ensures that // the JIT bindings in the parent injector don't change while we're being built synchronized (shellBuilder.lock()) { shells = shellBuilder.build(initializer, bindingData, stopwatch, errors); stopwatch.resetAndLog("Injector construction"); initializeStatically(); } injectDynamically(); if (shellBuilder.getStage() == Stage.TOOL) { // wrap the primaryInjector in a ToolStageInjector // to prevent non-tool-friendy methods from being called. return new ToolStageInjector(primaryInjector()); } else { return primaryInjector(); } } /** Initialize and validate everything. */ private void initializeStatically() { bindingData.initializeBindings(); stopwatch.resetAndLog("Binding initialization"); for (InjectorShell shell : shells) { shell.getInjector().index(); } stopwatch.resetAndLog("Binding indexing"); injectionRequestProcessor.process(shells); stopwatch.resetAndLog("Collecting injection requests"); bindingData.runCreationListeners(errors); stopwatch.resetAndLog("Binding validation"); injectionRequestProcessor.validate(); stopwatch.resetAndLog("Static validation"); initializer.validateOustandingInjections(errors); stopwatch.resetAndLog("Instance member validation"); new LookupProcessor(errors).process(shells); for (InjectorShell shell : shells) { ((DeferredLookups) shell.getInjector().lookups).initialize(errors); } stopwatch.resetAndLog("Provider verification"); for (InjectorShell shell : shells) { if (!shell.getElements().isEmpty()) { throw new AssertionError("Failed to execute " + shell.getElements()); } } errors.throwCreationExceptionIfErrorsExist(); } /** * Returns the injector being constructed. This is not necessarily the root injector. */ private Injector primaryInjector() { return shells.get(0).getInjector(); } /** * Inject everything that can be injected. This method is intentionally not synchronized. If we * locked while injecting members (ie. running user code), things would deadlock should the user * code build a just-in-time binding from another thread. */ private void injectDynamically() { injectionRequestProcessor.injectMembers(); stopwatch.resetAndLog("Static member injection"); initializer.injectAll(errors); stopwatch.resetAndLog("Instance injection"); errors.throwCreationExceptionIfErrorsExist(); if(shellBuilder.getStage() != Stage.TOOL) { for (InjectorShell shell : shells) { loadEagerSingletons(shell.getInjector(), shellBuilder.getStage(), errors); } stopwatch.resetAndLog("Preloading singletons"); } errors.throwCreationExceptionIfErrorsExist(); } /** * Loads eager singletons, or all singletons if we're in Stage.PRODUCTION. Bindings discovered * while we're binding these singletons are not be eager. */ void loadEagerSingletons(InjectorImpl injector, Stage stage, final Errors errors) { @SuppressWarnings("unchecked") // casting Collection to Collection is safe Iterable> candidateBindings = ImmutableList.copyOf(Iterables.concat( (Collection) injector.state.getExplicitBindingsThisLevel().values(), injector.jitBindings.values())); for (final BindingImpl binding : candidateBindings) { if (isEagerSingleton(injector, binding, stage)) { try { injector.callInContext(new ContextualCallable() { Dependency dependency = Dependency.get(binding.getKey()); public Void call(InternalContext context) { Dependency previous = context.setDependency(dependency); Errors errorsForBinding = errors.withSource(dependency); try { binding.getInternalFactory().get(errorsForBinding, context, dependency, false); } catch (ErrorsException e) { errorsForBinding.merge(e.getErrors()); } finally { context.setDependency(previous); } return null; } }); } catch (ErrorsException e) { throw new AssertionError(); } } } } private boolean isEagerSingleton(InjectorImpl injector, BindingImpl binding, Stage stage) { if (binding.getScoping().isEagerSingleton(stage)) { return true; } // handle a corner case where a child injector links to a binding in a parent injector, and // that binding is singleton. We won't catch this otherwise because we only iterate the child's // bindings. if (binding instanceof LinkedBindingImpl) { Key linkedBinding = ((LinkedBindingImpl) binding).getLinkedKey(); return isEagerSingleton(injector, injector.getBinding(linkedBinding), stage); } return false; } /** {@link Injector} exposed to users in {@link Stage#TOOL}. */ static class ToolStageInjector implements Injector { private final Injector delegateInjector; ToolStageInjector(Injector delegateInjector) { this.delegateInjector = delegateInjector; } public void injectMembers(Object o) { throw new UnsupportedOperationException( "Injector.injectMembers(Object) is not supported in Stage.TOOL"); } public Map, Binding> getBindings() { return this.delegateInjector.getBindings(); } public Map, Binding> getAllBindings() { return this.delegateInjector.getAllBindings(); } public Binding getBinding(Key key) { return this.delegateInjector.getBinding(key); } public Binding getBinding(Class type) { return this.delegateInjector.getBinding(type); } public Binding getExistingBinding(Key key) { return this.delegateInjector.getExistingBinding(key); } public List> findBindingsByType(TypeLiteral type) { return this.delegateInjector.findBindingsByType(type); } public Injector getParent() { return delegateInjector.getParent(); } public Injector createChildInjector(Iterable modules) { return delegateInjector.createChildInjector(modules); } public Injector createChildInjector(Module... modules) { return delegateInjector.createChildInjector(modules); } public Map, Scope> getScopeBindings() { return delegateInjector.getScopeBindings(); } public Set getTypeConverterBindings() { return delegateInjector.getTypeConverterBindings(); } public Provider getProvider(Key key) { throw new UnsupportedOperationException( "Injector.getProvider(Key) is not supported in Stage.TOOL"); } public Provider getProvider(Class type) { throw new UnsupportedOperationException( "Injector.getProvider(Class) is not supported in Stage.TOOL"); } public MembersInjector getMembersInjector(TypeLiteral typeLiteral) { throw new UnsupportedOperationException( "Injector.getMembersInjector(TypeLiteral) is not supported in Stage.TOOL"); } public MembersInjector getMembersInjector(Class type) { throw new UnsupportedOperationException( "Injector.getMembersInjector(Class) is not supported in Stage.TOOL"); } public T getInstance(Key key) { throw new UnsupportedOperationException( "Injector.getInstance(Key) is not supported in Stage.TOOL"); } public T getInstance(Class type) { throw new UnsupportedOperationException( "Injector.getInstance(Class) is not supported in Stage.TOOL"); } } } guice-3.0/core/src/com/google/inject/internal/InheritingState.java0000644000175000017500000001222211532155062025150 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.Scope; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Maps; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.spi.TypeConverterBinding; import com.google.inject.spi.TypeListenerBinding; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; /** * @author jessewilson@google.com (Jesse Wilson) */ final class InheritingState implements State { private final State parent; // Must be a linked hashmap in order to preserve order of bindings in Modules. private final Map, Binding> explicitBindingsMutable = Maps.newLinkedHashMap(); private final Map, Binding> explicitBindings = Collections.unmodifiableMap(explicitBindingsMutable); private final Map, Scope> scopes = Maps.newHashMap(); private final List converters = Lists.newArrayList(); /*if[AOP]*/ private final List methodAspects = Lists.newArrayList(); /*end[AOP]*/ private final List listenerBindings = Lists.newArrayList(); private final WeakKeySet blacklistedKeys = new WeakKeySet(); private final Object lock; InheritingState(State parent) { this.parent = checkNotNull(parent, "parent"); this.lock = (parent == State.NONE) ? this : parent.lock(); } public State parent() { return parent; } @SuppressWarnings("unchecked") // we only put in BindingImpls that match their key types public BindingImpl getExplicitBinding(Key key) { Binding binding = explicitBindings.get(key); return binding != null ? (BindingImpl) binding : parent.getExplicitBinding(key); } public Map, Binding> getExplicitBindingsThisLevel() { return explicitBindings; } public void putBinding(Key key, BindingImpl binding) { explicitBindingsMutable.put(key, binding); } public Scope getScope(Class annotationType) { Scope scope = scopes.get(annotationType); return scope != null ? scope : parent.getScope(annotationType); } public void putAnnotation(Class annotationType, Scope scope) { scopes.put(annotationType, scope); } public Iterable getConvertersThisLevel() { return converters; } public void addConverter(TypeConverterBinding typeConverterBinding) { converters.add(typeConverterBinding); } public TypeConverterBinding getConverter( String stringValue, TypeLiteral type, Errors errors, Object source) { TypeConverterBinding matchingConverter = null; for (State s = this; s != State.NONE; s = s.parent()) { for (TypeConverterBinding converter : s.getConvertersThisLevel()) { if (converter.getTypeMatcher().matches(type)) { if (matchingConverter != null) { errors.ambiguousTypeConversion(stringValue, source, type, matchingConverter, converter); } matchingConverter = converter; } } } return matchingConverter; } /*if[AOP]*/ public void addMethodAspect(MethodAspect methodAspect) { methodAspects.add(methodAspect); } public ImmutableList getMethodAspects() { return new ImmutableList.Builder() .addAll(parent.getMethodAspects()) .addAll(methodAspects) .build(); } /*end[AOP]*/ public void addTypeListener(TypeListenerBinding listenerBinding) { listenerBindings.add(listenerBinding); } public List getTypeListenerBindings() { List parentBindings = parent.getTypeListenerBindings(); List result = new ArrayList(parentBindings.size() + 1); result.addAll(parentBindings); result.addAll(listenerBindings); return result; } public void blacklist(Key key, Object source) { parent.blacklist(key, source); blacklistedKeys.add(key, source); } public boolean isBlacklisted(Key key) { return blacklistedKeys.contains(key); } public Set getSourcesForBlacklistedKey(Key key) { return blacklistedKeys.getSources(key); } public Object lock() { return lock; } public Map, Scope> getScopes() { return scopes; } } guice-3.0/core/src/com/google/inject/internal/AbstractProcessor.java0000644000175000017500000000414411501202012025476 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.spi.DefaultElementVisitor; import com.google.inject.spi.Element; import java.util.Iterator; import java.util.List; /** * Abstract base class for creating an injector from module elements. * *

Extending classes must return {@code true} from any overridden * {@code visit*()} methods, in order for the element processor to remove the * handled element. * * @author jessewilson@google.com (Jesse Wilson) */ abstract class AbstractProcessor extends DefaultElementVisitor { protected Errors errors; protected InjectorImpl injector; protected AbstractProcessor(Errors errors) { this.errors = errors; } public void process(Iterable isolatedInjectorBuilders) { for (InjectorShell injectorShell : isolatedInjectorBuilders) { process(injectorShell.getInjector(), injectorShell.getElements()); } } public void process(InjectorImpl injector, List elements) { Errors errorsAnyElement = this.errors; this.injector = injector; try { for (Iterator i = elements.iterator(); i.hasNext(); ) { Element element = i.next(); this.errors = errorsAnyElement.withSource(element.getSource()); Boolean allDone = element.acceptVisitor(this); if (allDone) { i.remove(); } } } finally { this.errors = errorsAnyElement; this.injector = null; } } @Override protected Boolean visitOther(Element element) { return false; } } guice-3.0/core/src/com/google/inject/internal/MethodAspect.java0000644000175000017500000000435711460133000024425 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.matcher.Matcher; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import org.aopalliance.intercept.MethodInterceptor; /** * Ties a matcher to a method interceptor. * * @author crazybob@google.com (Bob Lee) */ final class MethodAspect { private final Matcher> classMatcher; private final Matcher methodMatcher; private final List interceptors; /** * @param classMatcher matches classes the interceptor should apply to. For example: {@code * only(Runnable.class)}. * @param methodMatcher matches methods the interceptor should apply to. For example: {@code * annotatedWith(Transactional.class)}. * @param interceptors to apply */ MethodAspect(Matcher> classMatcher, Matcher methodMatcher, List interceptors) { this.classMatcher = checkNotNull(classMatcher, "class matcher"); this.methodMatcher = checkNotNull(methodMatcher, "method matcher"); this.interceptors = checkNotNull(interceptors, "interceptors"); } MethodAspect(Matcher> classMatcher, Matcher methodMatcher, MethodInterceptor... interceptors) { this(classMatcher, methodMatcher, Arrays.asList(interceptors)); } boolean matches(Class clazz) { return classMatcher.matches(clazz); } boolean matches(Method method) { return methodMatcher.matches(method); } List interceptors() { return interceptors; } } guice-3.0/core/src/com/google/inject/internal/DelegatingInvocationHandler.java0000644000175000017500000000323111460133000027426 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; class DelegatingInvocationHandler implements InvocationHandler { private T delegate; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (delegate == null) { throw new IllegalStateException("This is a proxy used to support" + " circular references involving constructors. The object we're" + " proxying is not constructed yet. Please wait until after" + " injection has completed to use this object."); } try { return method.invoke(delegate, args); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw e.getTargetException(); } } public T getDelegate() { return delegate; } void setDelegate(T delegate) { this.delegate = delegate; } } guice-3.0/core/src/com/google/inject/internal/ConstructionContext.java0000644000175000017500000000506211460133000026076 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; /** * Context of a dependency construction. Used to manage circular references. * * @author crazybob@google.com (Bob Lee) */ final class ConstructionContext { T currentReference; boolean constructing; List> invocationHandlers; public T getCurrentReference() { return currentReference; } public void removeCurrentReference() { this.currentReference = null; } public void setCurrentReference(T currentReference) { this.currentReference = currentReference; } public boolean isConstructing() { return constructing; } public void startConstruction() { this.constructing = true; } public void finishConstruction() { this.constructing = false; invocationHandlers = null; } public Object createProxy(Errors errors, Class expectedType) throws ErrorsException { // TODO: if I create a proxy which implements all the interfaces of // the implementation type, I'll be able to get away with one proxy // instance (as opposed to one per caller). if (!expectedType.isInterface()) { throw errors.cannotSatisfyCircularDependency(expectedType).toException(); } if (invocationHandlers == null) { invocationHandlers = new ArrayList>(); } DelegatingInvocationHandler invocationHandler = new DelegatingInvocationHandler(); invocationHandlers.add(invocationHandler); ClassLoader classLoader = BytecodeGen.getClassLoader(expectedType); return expectedType.cast(Proxy.newProxyInstance(classLoader, new Class[] { expectedType, CircularDependencyProxy.class }, invocationHandler)); } public void setProxyDelegates(T delegate) { if (invocationHandlers != null) { for (DelegatingInvocationHandler handler : invocationHandlers) { handler.setDelegate(delegate); } } } } guice-3.0/core/src/com/google/inject/internal/DeferredLookups.java0000644000175000017500000000405011460133000025130 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Key; import com.google.inject.MembersInjector; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.Lists; import com.google.inject.spi.Element; import com.google.inject.spi.MembersInjectorLookup; import com.google.inject.spi.ProviderLookup; import java.util.List; /** * Returns providers and members injectors that haven't yet been initialized. As a part of injector * creation it's necessary to {@link #initialize initialize} these lookups. * * @author jessewilson@google.com (Jesse Wilson) */ final class DeferredLookups implements Lookups { private final InjectorImpl injector; private final List lookups = Lists.newArrayList(); DeferredLookups(InjectorImpl injector) { this.injector = injector; } /** * Initialize the specified lookups, either immediately or when the injector is created. */ void initialize(Errors errors) { injector.lookups = injector; new LookupProcessor(errors).process(injector, lookups); } public Provider getProvider(Key key) { ProviderLookup lookup = new ProviderLookup(key, key); lookups.add(lookup); return lookup.getProvider(); } public MembersInjector getMembersInjector(TypeLiteral type) { MembersInjectorLookup lookup = new MembersInjectorLookup(type, type); lookups.add(lookup); return lookup.getMembersInjector(); } } guice-3.0/core/src/com/google/inject/internal/ProviderMethodsModule.java0000644000175000017500000001333411530462654026346 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.Provides; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.spi.Dependency; import com.google.inject.spi.Message; import com.google.inject.util.Modules; import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.List; import java.util.logging.Logger; /** * Creates bindings to methods annotated with {@literal @}{@link Provides}. Use the scope and * binding annotations on the provider method to configure the binding. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ public final class ProviderMethodsModule implements Module { private final Object delegate; private final TypeLiteral typeLiteral; private ProviderMethodsModule(Object delegate) { this.delegate = checkNotNull(delegate, "delegate"); this.typeLiteral = TypeLiteral.get(this.delegate.getClass()); } /** * Returns a module which creates bindings for provider methods from the given module. */ public static Module forModule(Module module) { return forObject(module); } /** * Returns a module which creates bindings for provider methods from the given object. * This is useful notably for GIN */ public static Module forObject(Object object) { // avoid infinite recursion, since installing a module always installs itself if (object instanceof ProviderMethodsModule) { return Modules.EMPTY_MODULE; } return new ProviderMethodsModule(object); } public synchronized void configure(Binder binder) { for (ProviderMethod providerMethod : getProviderMethods(binder)) { providerMethod.configure(binder); } } public List> getProviderMethods(Binder binder) { List> result = Lists.newArrayList(); for (Class c = delegate.getClass(); c != Object.class; c = c.getSuperclass()) { for (Method method : c.getDeclaredMethods()) { if (method.isAnnotationPresent(Provides.class)) { result.add(createProviderMethod(binder, method)); } } } return result; } ProviderMethod createProviderMethod(Binder binder, final Method method) { binder = binder.withSource(method); Errors errors = new Errors(method); // prepare the parameter providers List> dependencies = Lists.newArrayList(); List> parameterProviders = Lists.newArrayList(); List> parameterTypes = typeLiteral.getParameterTypes(method); Annotation[][] parameterAnnotations = method.getParameterAnnotations(); for (int i = 0; i < parameterTypes.size(); i++) { Key key = getKey(errors, parameterTypes.get(i), method, parameterAnnotations[i]); if(key.equals(Key.get(Logger.class))) { // If it was a Logger, change the key to be unique & bind it to a // provider that provides a logger with a proper name. // This solves issue 482 (returning a new anonymous logger on every call exhausts memory) Key loggerKey = Key.get(Logger.class, UniqueAnnotations.create()); binder.bind(loggerKey).toProvider(new LogProvider(method)); key = loggerKey; } dependencies.add(Dependency.get(key)); parameterProviders.add(binder.getProvider(key)); } @SuppressWarnings("unchecked") // Define T as the method's return type. TypeLiteral returnType = (TypeLiteral) typeLiteral.getReturnType(method); Key key = getKey(errors, returnType, method, method.getAnnotations()); Class scopeAnnotation = Annotations.findScopeAnnotation(errors, method.getAnnotations()); for (Message message : errors.getMessages()) { binder.addError(message); } return new ProviderMethod(key, method, delegate, ImmutableSet.copyOf(dependencies), parameterProviders, scopeAnnotation); } Key getKey(Errors errors, TypeLiteral type, Member member, Annotation[] annotations) { Annotation bindingAnnotation = Annotations.findBindingAnnotation(errors, member, annotations); return bindingAnnotation == null ? Key.get(type) : Key.get(type, bindingAnnotation); } @Override public boolean equals(Object o) { return o instanceof ProviderMethodsModule && ((ProviderMethodsModule) o).delegate == delegate; } @Override public int hashCode() { return delegate.hashCode(); } /** A provider that returns a logger based on the method name. */ private static final class LogProvider implements Provider { private final String name; public LogProvider(Method method) { this.name = method.getDeclaringClass().getName() + "." + method.getName(); } public Logger get() { return Logger.getLogger(name); } } } guice-3.0/core/src/com/google/inject/internal/FailableCache.java0000644000175000017500000000402411461631440024473 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.util.Function; import com.google.inject.internal.util.MapMaker; import com.google.inject.internal.util.Nullable; import java.util.Map; /** * Lazily creates (and caches) values for keys. If creating the value fails (with errors), an * exception is thrown on retrieval. * * @author jessewilson@google.com (Jesse Wilson) */ public abstract class FailableCache { private final Map delegate = new MapMaker().makeComputingMap( new Function() { public Object apply(@Nullable K key) { Errors errors = new Errors(); V result = null; try { result = FailableCache.this.create(key, errors); } catch (ErrorsException e) { errors.merge(e.getErrors()); } return errors.hasErrors() ? errors : result; } }); protected abstract V create(K key, Errors errors) throws ErrorsException; public V get(K key, Errors errors) throws ErrorsException { Object resultOrError = delegate.get(key); if (resultOrError instanceof Errors) { errors.merge((Errors) resultOrError); throw errors.toException(); } else { @SuppressWarnings("unchecked") // create returned a non-error result, so this is safe V result = (V) resultOrError; return result; } } boolean remove(K key) { return delegate.remove(key) != null; } } guice-3.0/core/src/com/google/inject/internal/ErrorsException.java0000644000175000017500000000213011460133000025163 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; /** * Indicates that a result could not be returned while preparing or resolving a binding. The caller * should {@link Errors#merge(Errors) merge} the errors from this exception with their existing * errors. * * @author jessewilson@google.com (Jesse Wilson) */ public class ErrorsException extends Exception { private final Errors errors; public ErrorsException(Errors errors) { this.errors = errors; } public Errors getErrors() { return errors; } } guice-3.0/core/src/com/google/inject/internal/BindingProcessor.java0000644000175000017500000001610111536234254025326 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.spi.ConstructorBinding; import com.google.inject.spi.ConvertedConstantBinding; import com.google.inject.spi.ExposedBinding; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.InstanceBinding; import com.google.inject.spi.LinkedKeyBinding; import com.google.inject.spi.PrivateElements; import com.google.inject.spi.ProviderBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderKeyBinding; import com.google.inject.spi.UntargettedBinding; import java.util.Set; /** * Handles {@link Binder#bind} and {@link Binder#bindConstant} elements. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ final class BindingProcessor extends AbstractBindingProcessor { private final Initializer initializer; BindingProcessor(Errors errors, Initializer initializer, ProcessedBindingData bindingData) { super(errors, bindingData); this.initializer = initializer; } @Override public Boolean visit(Binding command) { Class rawType = command.getKey().getTypeLiteral().getRawType(); if (Void.class.equals(rawType)) { if (command instanceof ProviderInstanceBinding && ((ProviderInstanceBinding) command).getProviderInstance() instanceof ProviderMethod) { errors.voidProviderMethod(); } else { errors.missingConstantValues(); } return true; } if (rawType == Provider.class) { errors.bindingToProvider(); return true; } return command.acceptTargetVisitor(new Processor((BindingImpl)command) { public Boolean visit(ConstructorBinding binding) { prepareBinding(); try { ConstructorBindingImpl onInjector = ConstructorBindingImpl.create(injector, key, binding.getConstructor(), source, scoping, errors, false); scheduleInitialization(onInjector); putBinding(onInjector); } catch (ErrorsException e) { errors.merge(e.getErrors()); putBinding(invalidBinding(injector, key, source)); } return true; } public Boolean visit(InstanceBinding binding) { prepareBinding(); Set injectionPoints = binding.getInjectionPoints(); T instance = binding.getInstance(); Initializable ref = initializer.requestInjection( injector, instance, source, injectionPoints); ConstantFactory factory = new ConstantFactory(ref); InternalFactory scopedFactory = Scoping.scope(key, injector, factory, source, scoping); putBinding(new InstanceBindingImpl(injector, key, source, scopedFactory, injectionPoints, instance)); return true; } public Boolean visit(ProviderInstanceBinding binding) { prepareBinding(); Provider provider = binding.getProviderInstance(); Set injectionPoints = binding.getInjectionPoints(); Initializable> initializable = initializer .>requestInjection(injector, provider, source, injectionPoints); InternalFactory factory = new InternalFactoryToProviderAdapter(initializable, source); InternalFactory scopedFactory = Scoping.scope(key, injector, factory, source, scoping); putBinding(new ProviderInstanceBindingImpl(injector, key, source, scopedFactory, scoping, provider, injectionPoints)); return true; } public Boolean visit(ProviderKeyBinding binding) { prepareBinding(); Key> providerKey = binding.getProviderKey(); BoundProviderFactory boundProviderFactory = new BoundProviderFactory(injector, providerKey, source); bindingData.addCreationListener(boundProviderFactory); InternalFactory scopedFactory = Scoping.scope( key, injector, (InternalFactory) boundProviderFactory, source, scoping); putBinding(new LinkedProviderBindingImpl( injector, key, source, scopedFactory, scoping, providerKey)); return true; } public Boolean visit(LinkedKeyBinding binding) { prepareBinding(); Key linkedKey = binding.getLinkedKey(); if (key.equals(linkedKey)) { errors.recursiveBinding(); } FactoryProxy factory = new FactoryProxy(injector, key, linkedKey, source); bindingData.addCreationListener(factory); InternalFactory scopedFactory = Scoping.scope(key, injector, factory, source, scoping); putBinding( new LinkedBindingImpl(injector, key, source, scopedFactory, scoping, linkedKey)); return true; } public Boolean visit(UntargettedBinding untargetted) { return false; } public Boolean visit(ExposedBinding binding) { throw new IllegalArgumentException("Cannot apply a non-module element"); } public Boolean visit(ConvertedConstantBinding binding) { throw new IllegalArgumentException("Cannot apply a non-module element"); } public Boolean visit(ProviderBinding binding) { throw new IllegalArgumentException("Cannot apply a non-module element"); } @Override protected Boolean visitOther(Binding binding) { throw new IllegalStateException("BindingProcessor should override all visitations"); } }); } @Override public Boolean visit(PrivateElements privateElements) { for (Key key : privateElements.getExposedKeys()) { bindExposed(privateElements, key); } return false; // leave the private elements for the PrivateElementsProcessor to handle } private void bindExposed(PrivateElements privateElements, Key key) { ExposedKeyFactory exposedKeyFactory = new ExposedKeyFactory(key, privateElements); bindingData.addCreationListener(exposedKeyFactory); putBinding(new ExposedBindingImpl( injector, privateElements.getExposedSource(key), key, exposedKeyFactory, privateElements)); } } guice-3.0/core/src/com/google/inject/internal/SingleParameterInjector.java0000644000175000017500000000432111460133000026614 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.spi.Dependency; /** * Resolves a single parameter, to be used in a constructor or method invocation. */ final class SingleParameterInjector { private static final Object[] NO_ARGUMENTS = {}; private final Dependency dependency; private final InternalFactory factory; SingleParameterInjector(Dependency dependency, InternalFactory factory) { this.dependency = dependency; this.factory = factory; } private T inject(Errors errors, InternalContext context) throws ErrorsException { Dependency previous = context.setDependency(dependency); try { return factory.get(errors.withSource(dependency), context, dependency, false); } finally { context.setDependency(previous); } } /** * Returns an array of parameter values. */ static Object[] getAll(Errors errors, InternalContext context, SingleParameterInjector[] parameterInjectors) throws ErrorsException { if (parameterInjectors == null) { return NO_ARGUMENTS; } int numErrorsBefore = errors.size(); int size = parameterInjectors.length; Object[] parameters = new Object[size]; // optimization: use manual for/each to save allocating an iterator here for (int i = 0; i < size; i++) { SingleParameterInjector parameterInjector = parameterInjectors[i]; try { parameters[i] = parameterInjector.inject(errors, context); } catch (ErrorsException e) { errors.merge(e.getErrors()); } } errors.throwIfNewErrors(numErrorsBefore); return parameters; } } guice-3.0/core/src/com/google/inject/internal/ConstructionProxyFactory.java0000644000175000017500000000160711461132500027131 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; /** * Creates {@link ConstructionProxy} instances. * * @author crazybob@google.com (Bob Lee) */ interface ConstructionProxyFactory { /** * Gets a construction proxy for the given constructor. */ ConstructionProxy create() throws ErrorsException; } guice-3.0/core/src/com/google/inject/internal/AbstractBindingProcessor.java0000644000175000017500000001345311536234346027023 0ustar drazzibdrazzib/** * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import java.util.Set; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Binding; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.MembersInjector; import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.spi.DefaultBindingTargetVisitor; /** * Guarantees that processing of Binding elements happens in a sane way. * * @author sameb@google.com (Sam Berlin) */ abstract class AbstractBindingProcessor extends AbstractProcessor { // It's unfortunate that we have to maintain a blacklist of specific // classes, but we can't easily block the whole package because of // all our unit tests. private static final Set> FORBIDDEN_TYPES = ImmutableSet.>of( AbstractModule.class, Binder.class, Binding.class, Injector.class, Key.class, MembersInjector.class, Module.class, Provider.class, Scope.class, TypeLiteral.class); // TODO(jessewilson): fix BuiltInModule, then add Stage protected final ProcessedBindingData bindingData; AbstractBindingProcessor(Errors errors, ProcessedBindingData bindingData) { super(errors); this.bindingData = bindingData; } protected UntargettedBindingImpl invalidBinding( InjectorImpl injector, Key key, Object source) { return new UntargettedBindingImpl(injector, key, source); } protected void putBinding(BindingImpl binding) { Key key = binding.getKey(); Class rawType = key.getTypeLiteral().getRawType(); if (FORBIDDEN_TYPES.contains(rawType)) { errors.cannotBindToGuiceType(rawType.getSimpleName()); return; } BindingImpl original = injector.getExistingBinding(key); if (original != null) { // If it failed because of an explicit duplicate binding... if (injector.state.getExplicitBinding(key) != null) { try { if(!isOkayDuplicate(original, binding, injector.state)) { errors.bindingAlreadySet(key, original.getSource()); return; } } catch(Throwable t) { errors.errorCheckingDuplicateBinding(key, original.getSource(), t); return; } } else { // Otherwise, it failed because of a duplicate JIT binding // in the parent errors.jitBindingAlreadySet(key); return; } } // prevent the parent from creating a JIT binding for this key injector.state.parent().blacklist(key, binding.getSource()); injector.state.putBinding(key, binding); } /** * We tolerate duplicate bindings if one exposes the other or if the two bindings * are considered duplicates (see {@link Bindings#areDuplicates(BindingImpl, BindingImpl)}. * * @param original the binding in the parent injector (candidate for an exposing binding) * @param binding the binding to check (candidate for the exposed binding) */ private boolean isOkayDuplicate(BindingImpl original, BindingImpl binding, State state) { if (original instanceof ExposedBindingImpl) { ExposedBindingImpl exposed = (ExposedBindingImpl) original; InjectorImpl exposedFrom = (InjectorImpl) exposed.getPrivateElements().getInjector(); return (exposedFrom == binding.getInjector()); } else { original = (BindingImpl)state.getExplicitBindingsThisLevel().get(binding.getKey()); // If no original at this level, the original was on a parent, and we don't // allow deduplication between parents & children. if(original == null) { return false; } else { return original.equals(binding); } } } private void validateKey(Object source, Key key) { Annotations.checkForMisplacedScopeAnnotations( key.getTypeLiteral().getRawType(), source, errors); } /** * Processor for visiting bindings. Each overriden method that wants to * actually process the binding should call prepareBinding first. */ abstract class Processor extends DefaultBindingTargetVisitor { final Object source; final Key key; final Class rawType; Scoping scoping; Processor(BindingImpl binding) { source = binding.getSource(); key = binding.getKey(); rawType = key.getTypeLiteral().getRawType(); scoping = binding.getScoping(); } protected void prepareBinding() { validateKey(source, key); scoping = Scoping.makeInjectable(scoping, injector, errors); } protected void scheduleInitialization(final BindingImpl binding) { bindingData.addUninitializedBinding(new Runnable() { public void run() { try { binding.getInjector().initializeBinding(binding, errors.withSource(source)); } catch (ErrorsException e) { errors.merge(e.getErrors()); } } }); } } } guice-3.0/core/src/com/google/inject/internal/UntargettedBindingProcessor.java0000644000175000017500000000444011536236056027542 0ustar drazzibdrazzib/** * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binding; import com.google.inject.spi.UntargettedBinding; /** * Processes just UntargettedBindings. * * @author sameb@google.com (Sam Berlin) */ class UntargettedBindingProcessor extends AbstractBindingProcessor { UntargettedBindingProcessor(Errors errors, ProcessedBindingData bindingData) { super(errors, bindingData); } @Override public Boolean visit(Binding binding) { return binding.acceptTargetVisitor(new Processor((BindingImpl)binding) { public Boolean visit(UntargettedBinding untargetted) { prepareBinding(); // Error: Missing implementation. // Example: bind(Date.class).annotatedWith(Red.class); // We can't assume abstract types aren't injectable. They may have an // @ImplementedBy annotation or something. if (key.getAnnotationType() != null) { errors.missingImplementation(key); putBinding(invalidBinding(injector, key, source)); return true; } // This cast is safe after the preceeding check. try { BindingImpl binding = injector.createUninitializedBinding( key, scoping, source, errors, false); scheduleInitialization(binding); putBinding(binding); } catch (ErrorsException e) { errors.merge(e.getErrors()); putBinding(invalidBinding(injector, key, source)); } return true; } @Override protected Boolean visitOther(Binding binding) { return false; } }); } } guice-3.0/core/src/com/google/inject/internal/PrivateElementsImpl.java0000644000175000017500000001057111460133000025771 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.PrivateBinder; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Maps; import static com.google.inject.internal.util.Preconditions.checkArgument; import static com.google.inject.internal.util.Preconditions.checkNotNull; import static com.google.inject.internal.util.Preconditions.checkState; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.Element; import com.google.inject.spi.ElementVisitor; import com.google.inject.spi.PrivateElements; import java.util.List; import java.util.Map; import java.util.Set; /** * @author jessewilson@google.com (Jesse Wilson) */ public final class PrivateElementsImpl implements PrivateElements { /* * This class acts as both a value object and as a builder. When getElements() is called, an * immutable collection of elements is constructed and the original mutable list is nulled out. * Similarly, the exposed keys are made immutable on access. */ private final Object source; private List elementsMutable = Lists.newArrayList(); private List> exposureBuilders = Lists.newArrayList(); /** lazily instantiated */ private ImmutableList elements; /** lazily instantiated */ private ImmutableMap, Object> exposedKeysToSources; private Injector injector; public PrivateElementsImpl(Object source) { this.source = checkNotNull(source, "source"); } public Object getSource() { return source; } public List getElements() { if (elements == null) { elements = ImmutableList.copyOf(elementsMutable); elementsMutable = null; } return elements; } public Injector getInjector() { return injector; } public void initInjector(Injector injector) { checkState(this.injector == null, "injector already initialized"); this.injector = checkNotNull(injector, "injector"); } public Set> getExposedKeys() { if (exposedKeysToSources == null) { Map, Object> exposedKeysToSourcesMutable = Maps.newLinkedHashMap(); for (ExposureBuilder exposureBuilder : exposureBuilders) { exposedKeysToSourcesMutable.put(exposureBuilder.getKey(), exposureBuilder.getSource()); } exposedKeysToSources = ImmutableMap.copyOf(exposedKeysToSourcesMutable); exposureBuilders = null; } return exposedKeysToSources.keySet(); } public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } public List getElementsMutable() { return elementsMutable; } public void addExposureBuilder(ExposureBuilder exposureBuilder) { exposureBuilders.add(exposureBuilder); } public void applyTo(Binder binder) { PrivateBinder privateBinder = binder.withSource(source).newPrivateBinder(); for (Element element : getElements()) { element.applyTo(privateBinder); } getExposedKeys(); // ensure exposedKeysToSources is populated for (Map.Entry, Object> entry : exposedKeysToSources.entrySet()) { privateBinder.withSource(entry.getValue()).expose(entry.getKey()); } } public Object getExposedSource(Key key) { getExposedKeys(); // ensure exposedKeysToSources is populated Object source = exposedKeysToSources.get(key); checkArgument(source != null, "%s not exposed by %s.", key, this); return source; } @Override public String toString() { return new ToStringBuilder(PrivateElements.class) .add("exposedKeys", getExposedKeys()) .add("source", getSource()) .toString(); } } guice-3.0/core/src/com/google/inject/internal/InjectionRequestProcessor.java0000644000175000017500000001015111460133000027225 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.ConfigurationException; import com.google.inject.Stage; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Lists; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.InjectionRequest; import com.google.inject.spi.StaticInjectionRequest; import java.util.List; import java.util.Set; /** * Handles {@code Binder.requestInjection} and {@code Binder.requestStaticInjection} commands. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) * @author mikeward@google.com (Mike Ward) */ final class InjectionRequestProcessor extends AbstractProcessor { private final List staticInjections = Lists.newArrayList(); private final Initializer initializer; InjectionRequestProcessor(Errors errors, Initializer initializer) { super(errors); this.initializer = initializer; } @Override public Boolean visit(StaticInjectionRequest request) { staticInjections.add(new StaticInjection(injector, request)); return true; } @Override public Boolean visit(InjectionRequest request) { Set injectionPoints; try { injectionPoints = request.getInjectionPoints(); } catch (ConfigurationException e) { errors.merge(e.getErrorMessages()); injectionPoints = e.getPartialValue(); } initializer.requestInjection( injector, request.getInstance(), request.getSource(), injectionPoints); return true; } void validate() { for (StaticInjection staticInjection : staticInjections) { staticInjection.validate(); } } void injectMembers() { /* * TODO: If you request both a parent class and one of its * subclasses, the parent class's static members will be * injected twice. */ for (StaticInjection staticInjection : staticInjections) { staticInjection.injectMembers(); } } /** A requested static injection. */ private class StaticInjection { final InjectorImpl injector; final Object source; final StaticInjectionRequest request; ImmutableList memberInjectors; public StaticInjection(InjectorImpl injector, StaticInjectionRequest request) { this.injector = injector; this.source = request.getSource(); this.request = request; } void validate() { Errors errorsForMember = errors.withSource(source); Set injectionPoints; try { injectionPoints = request.getInjectionPoints(); } catch (ConfigurationException e) { errors.merge(e.getErrorMessages()); injectionPoints = e.getPartialValue(); } memberInjectors = injector.membersInjectorStore.getInjectors( injectionPoints, errorsForMember); } void injectMembers() { try { injector.callInContext(new ContextualCallable() { public Void call(InternalContext context) { for (SingleMemberInjector memberInjector : memberInjectors) { // Run injections if we're not in tool stage (ie, PRODUCTION or DEV), // or if we are in tool stage and the injection point is toolable. if(injector.options.stage != Stage.TOOL || memberInjector.getInjectionPoint().isToolable()) { memberInjector.inject(errors, context, null); } } return null; } }); } catch (ErrorsException e) { throw new AssertionError(); } } } } guice-3.0/core/src/com/google/inject/internal/UniqueAnnotations.java0000644000175000017500000000376311460133000025531 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.BindingAnnotation; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.util.concurrent.atomic.AtomicInteger; /** * @author jessewilson@google.com (Jesse Wilson) */ public class UniqueAnnotations { private UniqueAnnotations() {} private static final AtomicInteger nextUniqueValue = new AtomicInteger(1); /** * Returns an annotation instance that is not equal to any other annotation * instances, for use in creating distinct {@link com.google.inject.Key}s. */ public static Annotation create() { return create(nextUniqueValue.getAndIncrement()); } static Annotation create(final int value) { return new Internal() { public int value() { return value; } public Class annotationType() { return Internal.class; } @Override public String toString() { return "@" + Internal.class.getName() + "(value=" + value + ")"; } @Override public boolean equals(Object o) { return o instanceof Internal && ((Internal) o).value() == value(); } @Override public int hashCode() { return (127 * "value".hashCode()) ^ value; } }; } @Retention(RUNTIME) @BindingAnnotation @interface Internal { int value(); } } guice-3.0/core/src/com/google/inject/internal/BindingBuilder.java0000644000175000017500000001353311460133000024722 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.ConfigurationException; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.binder.ScopedBindingBuilder; import com.google.inject.internal.util.ImmutableSet; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.spi.Element; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.Message; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.util.List; import java.util.Set; /** * Bind a non-constant key. * * @author jessewilson@google.com (Jesse Wilson) */ public class BindingBuilder extends AbstractBindingBuilder implements AnnotatedBindingBuilder { public BindingBuilder(Binder binder, List elements, Object source, Key key) { super(binder, elements, source, key); } public BindingBuilder annotatedWith(Class annotationType) { annotatedWithInternal(annotationType); return this; } public BindingBuilder annotatedWith(Annotation annotation) { annotatedWithInternal(annotation); return this; } public BindingBuilder to(Class implementation) { return to(Key.get(implementation)); } public BindingBuilder to(TypeLiteral implementation) { return to(Key.get(implementation)); } public BindingBuilder to(Key linkedKey) { checkNotNull(linkedKey, "linkedKey"); checkNotTargetted(); BindingImpl base = getBinding(); setBinding(new LinkedBindingImpl( base.getSource(), base.getKey(), base.getScoping(), linkedKey)); return this; } public void toInstance(T instance) { checkNotTargetted(); // lookup the injection points, adding any errors to the binder's errors list Set injectionPoints; if (instance != null) { try { injectionPoints = InjectionPoint.forInstanceMethodsAndFields(instance.getClass()); } catch (ConfigurationException e) { copyErrorsToBinder(e); injectionPoints = e.getPartialValue(); } } else { binder.addError(BINDING_TO_NULL); injectionPoints = ImmutableSet.of(); } BindingImpl base = getBinding(); setBinding(new InstanceBindingImpl( base.getSource(), base.getKey(), Scoping.EAGER_SINGLETON, injectionPoints, instance)); } public BindingBuilder toProvider(Provider provider) { checkNotNull(provider, "provider"); checkNotTargetted(); // lookup the injection points, adding any errors to the binder's errors list Set injectionPoints; try { injectionPoints = InjectionPoint.forInstanceMethodsAndFields(provider.getClass()); } catch (ConfigurationException e) { copyErrorsToBinder(e); injectionPoints = e.getPartialValue(); } BindingImpl base = getBinding(); setBinding(new ProviderInstanceBindingImpl( base.getSource(), base.getKey(), base.getScoping(), injectionPoints, provider)); return this; } public BindingBuilder toProvider( Class> providerType) { return toProvider(Key.get(providerType)); } public BindingBuilder toProvider( TypeLiteral> providerType) { return toProvider(Key.get(providerType)); } public BindingBuilder toProvider( Key> providerKey) { checkNotNull(providerKey, "providerKey"); checkNotTargetted(); BindingImpl base = getBinding(); setBinding(new LinkedProviderBindingImpl( base.getSource(), base.getKey(), base.getScoping(), providerKey)); return this; } public ScopedBindingBuilder toConstructor(Constructor constructor) { return toConstructor(constructor, TypeLiteral.get(constructor.getDeclaringClass())); } public ScopedBindingBuilder toConstructor(Constructor constructor, TypeLiteral type) { checkNotNull(constructor, "constructor"); checkNotNull(type, "type"); checkNotTargetted(); BindingImpl base = getBinding(); Set injectionPoints; try { injectionPoints = InjectionPoint.forInstanceMethodsAndFields(type); } catch (ConfigurationException e) { copyErrorsToBinder(e); injectionPoints = e.getPartialValue(); } try { @SuppressWarnings("unchecked") // safe; constructor is a subtype of toConstruct InjectionPoint constructorPoint = InjectionPoint.forConstructor(constructor, type); setBinding(new ConstructorBindingImpl(base.getKey(), base.getSource(), base.getScoping(), constructorPoint, injectionPoints)); } catch (ConfigurationException e) { copyErrorsToBinder(e); } return this; } @Override public String toString() { return "BindingBuilder<" + getBinding().getKey().getTypeLiteral() + ">"; } private void copyErrorsToBinder(ConfigurationException e) { for (Message message : e.getErrorMessages()) { binder.addError(message); } } } guice-3.0/core/src/com/google/inject/internal/ExposedKeyFactory.java0000644000175000017500000000400111536227520025456 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Key; import com.google.inject.spi.Dependency; import com.google.inject.spi.PrivateElements; /** * This factory exists in a parent injector. When invoked, it retrieves its value from a child * injector. */ final class ExposedKeyFactory implements InternalFactory, CreationListener { private final Key key; private final PrivateElements privateElements; private BindingImpl delegate; ExposedKeyFactory(Key key, PrivateElements privateElements) { this.key = key; this.privateElements = privateElements; } public void notify(Errors errors) { InjectorImpl privateInjector = (InjectorImpl) privateElements.getInjector(); BindingImpl explicitBinding = privateInjector.state.getExplicitBinding(key); // validate that the child injector has its own factory. If the getInternalFactory() returns // this, then that child injector doesn't have a factory (and getExplicitBinding has returned // its parent's binding instead if (explicitBinding.getInternalFactory() == this) { errors.withSource(explicitBinding.getSource()).exposedButNotBound(key); return; } this.delegate = explicitBinding; } public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) throws ErrorsException { return delegate.getInternalFactory().get(errors, context, dependency, linked); } } guice-3.0/core/src/com/google/inject/internal/ExposureBuilder.java0000644000175000017500000000366411460133000025166 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.binder.AnnotatedElementBuilder; import com.google.inject.internal.util.Preconditions; import java.lang.annotation.Annotation; /** * For private binder's expose() method. */ public class ExposureBuilder implements AnnotatedElementBuilder { private final Binder binder; private final Object source; private Key key; public ExposureBuilder(Binder binder, Object source, Key key) { this.binder = binder; this.source = source; this.key = key; } protected void checkNotAnnotated() { if (key.getAnnotationType() != null) { binder.addError(AbstractBindingBuilder.ANNOTATION_ALREADY_SPECIFIED); } } public void annotatedWith(Class annotationType) { Preconditions.checkNotNull(annotationType, "annotationType"); checkNotAnnotated(); key = Key.get(key.getTypeLiteral(), annotationType); } public void annotatedWith(Annotation annotation) { Preconditions.checkNotNull(annotation, "annotation"); checkNotAnnotated(); key = Key.get(key.getTypeLiteral(), annotation); } public Key getKey() { return key; } public Object getSource() { return source; } @Override public String toString() { return "AnnotatedElementBuilder"; } }guice-3.0/core/src/com/google/inject/internal/Initializable.java0000644000175000017500000000164611460133000024623 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; /** * Holds a reference that requires initialization to be performed before it can be used. * * @author jessewilson@google.com (Jesse Wilson) */ interface Initializable { /** * Ensures the reference is initialized, then returns it. */ T get(Errors errors) throws ErrorsException; } guice-3.0/core/src/com/google/inject/internal/SingleMemberInjector.java0000644000175000017500000000155211460133000026106 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.spi.InjectionPoint; /** * Injects a field or method of a given object. */ interface SingleMemberInjector { void inject(Errors errors, InternalContext context, Object o); InjectionPoint getInjectionPoint(); } guice-3.0/core/src/com/google/inject/internal/ProviderInstanceBindingImpl.java0000644000175000017500000001023611502212010027426 0ustar drazzibdrazzib/* Copyright (C) 2007 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Objects; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import java.util.Set; final class ProviderInstanceBindingImpl extends BindingImpl implements ProviderInstanceBinding { final Provider providerInstance; final ImmutableSet injectionPoints; public ProviderInstanceBindingImpl(InjectorImpl injector, Key key, Object source, InternalFactory internalFactory, Scoping scoping, Provider providerInstance, Set injectionPoints) { super(injector, key, source, internalFactory, scoping); this.providerInstance = providerInstance; this.injectionPoints = ImmutableSet.copyOf(injectionPoints); } public ProviderInstanceBindingImpl(Object source, Key key, Scoping scoping, Set injectionPoints, Provider providerInstance) { super(source, key, scoping); this.injectionPoints = ImmutableSet.copyOf(injectionPoints); this.providerInstance = providerInstance; } @SuppressWarnings("unchecked") // the extension type is always consistent with the provider type public V acceptTargetVisitor(BindingTargetVisitor visitor) { if(providerInstance instanceof ProviderWithExtensionVisitor) { return ((ProviderWithExtensionVisitor) providerInstance) .acceptExtensionVisitor(visitor, this); } else { return visitor.visit(this); } } public Provider getProviderInstance() { return providerInstance; } public Set getInjectionPoints() { return injectionPoints; } public Set> getDependencies() { return providerInstance instanceof HasDependencies ? ImmutableSet.copyOf(((HasDependencies) providerInstance).getDependencies()) : Dependency.forInjectionPoints(injectionPoints); } public BindingImpl withScoping(Scoping scoping) { return new ProviderInstanceBindingImpl( getSource(), getKey(), scoping, injectionPoints, providerInstance); } public BindingImpl withKey(Key key) { return new ProviderInstanceBindingImpl( getSource(), key, getScoping(), injectionPoints, providerInstance); } public void applyTo(Binder binder) { getScoping().applyTo( binder.withSource(getSource()).bind(getKey()).toProvider(getProviderInstance())); } @Override public String toString() { return new ToStringBuilder(ProviderInstanceBinding.class) .add("key", getKey()) .add("source", getSource()) .add("scope", getScoping()) .add("provider", providerInstance) .toString(); } @Override public boolean equals(Object obj) { if(obj instanceof ProviderInstanceBindingImpl) { ProviderInstanceBindingImpl o = (ProviderInstanceBindingImpl)obj; return getKey().equals(o.getKey()) && getScoping().equals(o.getScoping()) && Objects.equal(providerInstance, o.providerInstance); } else { return false; } } @Override public int hashCode() { return Objects.hashCode(getKey(), getScoping()); } } guice-3.0/core/src/com/google/inject/internal/util/0000755000175000017500000000000011461631440022162 5ustar drazzibdrazzibguice-3.0/core/src/com/google/inject/internal/util/Stopwatch.java0000644000175000017500000000243511460132776025014 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.logging.Logger; /** * Enables simple performance monitoring. * * @author crazybob@google.com (Bob Lee) */ public final class Stopwatch { private static final Logger logger = Logger.getLogger(Stopwatch.class.getName()); private long start = System.currentTimeMillis(); /** * Resets and returns elapsed time in milliseconds. */ public long reset() { long now = System.currentTimeMillis(); try { return now - start; } finally { start = now; } } /** * Resets and logs elapsed time in milliseconds. */ public void resetAndLog(String label) { logger.fine(label + ": " + reset() + "ms"); } } guice-3.0/core/src/com/google/inject/internal/util/ImmutableCollection.java0000644000175000017500000001521011461631440026757 0ustar drazzibdrazzib/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.Serializable; import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; /** * An immutable collection. Does not permit null elements. * *

Note: Although this class is not final, it cannot be subclassed * outside of this package as it has no public or protected constructors. Thus, * instances of this type are guaranteed to be immutable. * * @author Jesse Wilson */ @SuppressWarnings("serial") // we're overriding default serialization public abstract class ImmutableCollection implements Collection, Serializable { static final ImmutableCollection EMPTY_IMMUTABLE_COLLECTION = new EmptyImmutableCollection(); /** Copied here for GWT compatibility. */ private static final Object[] EMPTY_ARRAY = new Object[0]; private static final UnmodifiableIterator EMPTY_ITERATOR = new UnmodifiableIterator() { public boolean hasNext() { return false; } public Object next() { throw new NoSuchElementException(); } }; ImmutableCollection() {} /** * Returns an unmodifiable iterator across the elements in this collection. */ public abstract UnmodifiableIterator iterator(); public Object[] toArray() { Object[] newArray = new Object[size()]; return toArray(newArray); } public T[] toArray(T[] other) { int size = size(); if (other.length < size) { other = ObjectArrays.newArray(other, size); } else if (other.length > size) { other[size] = null; } int index = 0; for (E element : this) { /* * Sleazy fake cast. However, if element is not a T, then the very next * line must fail with an ArrayStoreException, so we should be safe. */ @SuppressWarnings("unchecked") T elementAsT = (T) element; other[index++] = elementAsT; } return other; } public boolean contains(@Nullable Object object) { if (object == null) { return false; } for (E element : this) { if (element.equals(object)) { return true; } } return false; } public boolean containsAll(Collection targets) { for (Object target : targets) { if (!contains(target)) { return false; } } return true; } public boolean isEmpty() { return size() == 0; } @Override public String toString() { StringBuilder sb = new StringBuilder(size() * 16); sb.append('['); Iterator i = iterator(); if (i.hasNext()) { sb.append(i.next()); } while (i.hasNext()) { sb.append(", "); sb.append(i.next()); } return sb.append(']').toString(); } /** * Guaranteed to throw an exception and leave the collection unmodified. * * @throws UnsupportedOperationException always */ public final boolean add(E e) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the collection unmodified. * * @throws UnsupportedOperationException always */ public final boolean remove(Object object) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the collection unmodified. * * @throws UnsupportedOperationException always */ public final boolean addAll(Collection newElements) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the collection unmodified. * * @throws UnsupportedOperationException always */ public final boolean removeAll(Collection oldElements) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the collection unmodified. * * @throws UnsupportedOperationException always */ public final boolean retainAll(Collection elementsToKeep) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the collection unmodified. * * @throws UnsupportedOperationException always */ public final void clear() { throw new UnsupportedOperationException(); } private static class EmptyImmutableCollection extends ImmutableCollection { public int size() { return 0; } @Override public boolean isEmpty() { return true; } @Override public boolean contains(@Nullable Object object) { return false; } @Override public UnmodifiableIterator iterator() { return EMPTY_ITERATOR; } @Override public Object[] toArray() { return EMPTY_ARRAY; } @Override public T[] toArray(T[] array) { if (array.length > 0) { array[0] = null; } return array; } } private static class ArrayImmutableCollection extends ImmutableCollection { private final E[] elements; ArrayImmutableCollection(E[] elements) { this.elements = elements; } public int size() { return elements.length; } @Override public boolean isEmpty() { return false; } @Override public UnmodifiableIterator iterator() { return new UnmodifiableIterator() { int i = 0; public boolean hasNext() { return i < elements.length; } public E next() { if (!hasNext()) { throw new NoSuchElementException(); } return elements[i++]; } }; } } /* * Serializes ImmutableCollections as their logical contents. This ensures * that implementation types do not leak into the serialized representation. */ private static class SerializedForm implements Serializable { final Object[] elements; SerializedForm(Object[] elements) { this.elements = elements; } Object readResolve() { return elements.length == 0 ? EMPTY_IMMUTABLE_COLLECTION : new ArrayImmutableCollection(elements.clone()); } private static final long serialVersionUID = 0; } Object writeReplace() { return new SerializedForm(toArray()); } } guice-3.0/core/src/com/google/inject/internal/util/AbstractIterator.java0000644000175000017500000001204311460132776026311 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Iterator; import java.util.NoSuchElementException; /** * This class provides a skeletal implementation of the {@code Iterator} * interface, to make this interface easier to implement for certain types of * data sources. * *

{@code Iterator} requires its implementations to support querying the * end-of-data status without changing the iterator's state, using the {@link * #hasNext} method. But many data sources, such as {@link * java.io.Reader#read()}), do not expose this information; the only way to * discover whether there is any data left is by trying to retrieve it. These * types of data sources are ordinarily difficult to write iterators for. But * using this class, one must implement only the {@link #computeNext} method, * and invoke the {@link #endOfData} method when appropriate. * *

Another example is an iterator that skips over null elements in a backing * iterator. This could be implemented as:

   {@code
 *
 *   public static Iterator skipNulls(final Iterator in) {
 *     return new AbstractIterator() {
 *       protected String computeNext() {
 *         while (in.hasNext()) {
 *           String s = in.next();
 *           if (s != null) {
 *             return s;
 *           }
 *         }
 *         return endOfData();
 *       }
 *     };
 *   }}
* * This class supports iterators that include null elements. The {@link * #remove()} method throws an {@link UnsupportedOperationException}, but * this can be overridden to support removal. * * @author Kevin Bourrillion */ public abstract class AbstractIterator implements Iterator { private State state = State.NOT_READY; private enum State { /** We have computed the next element and haven't returned it yet. */ READY, /** We haven't yet computed or have already returned the element. */ NOT_READY, /** We have reached the end of the data and are finished. */ DONE, /** We've suffered an exception and are kaput. */ FAILED, } private T next; /** * Returns the next element. Note: the implementation must call {@link * #endOfData} when there are no elements left in the iteration. Failure to do * so could result in an infinite loop. * *

The initial invocation of {@link #hasNext()} or {@link #next()} calls * this method, as does the first invocation of {@code hasNext} or * {@code next} following each successful call to {@code next}. Once the * implementation either invokes {@code endOfData} or throws an exception, * {@code computeNext} is guaranteed to never be called again. * *

If this method throws an exception, it will propagate outward to the * {@code hasNext()} or {@code next()} invocation that invoked this method. * Any further attempts to use the iterator will result in an {@link * IllegalStateException}. * * @return the next element if there was one. If {@code endOfData} was called * during execution, the return value will be ignored. * @throws RuntimeException if any unrecoverable error happens. This exception * will propagate outward to the {@code hasNext()}, {@code next()}, or * {@code peek()} invocation that invoked this method. Any further * attempts to use the iterator will result in an * {@link IllegalStateException}. */ protected abstract T computeNext(); /** * Implementations of {@code computeNext} must invoke this method when * there are no elements left in the iteration. * * @return {@code null}; a convenience so your {@link #computeNext} * implementation can use the simple statement {@code return endOfData();} */ protected final T endOfData() { state = State.DONE; return null; } public boolean hasNext() { Preconditions.checkState(state != State.FAILED); switch (state) { case DONE: return false; case READY: return true; default: } return tryToComputeNext(); } private boolean tryToComputeNext() { state = State.FAILED; // temporary pessimism next = computeNext(); if (state != State.DONE) { state = State.READY; return true; } return false; } public T next() { if (!hasNext()) { throw new NoSuchElementException(); } state = State.NOT_READY; return next; } /** * This method is not supported. */ public void remove() { throw new UnsupportedOperationException(); } } guice-3.0/core/src/com/google/inject/internal/util/NullOutputException.java0000644000175000017500000000174011460132776027050 0ustar drazzibdrazzib/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; /** * Thrown when a computer function returns null. This subclass exists so * that our ReferenceCache adapter can differentiate null output from null * keys, but we don't want to make this public otherwise. * * @author Bob Lee */ class NullOutputException extends NullPointerException { public NullOutputException(String s) { super(s); } } guice-3.0/core/src/com/google/inject/internal/util/Objects.java0000644000175000017500000000405011461631440024415 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Arrays; /** * Helper functions that can operate on any {@code Object}. * * @author Laurence Gonsalves */ public final class Objects { private Objects() {} /** * Determines whether two possibly-null objects are equal. Returns: * *

    *
  • {@code true} if {@code a} and {@code b} are both null. *
  • {@code true} if {@code a} and {@code b} are both non-null and they are * equal according to {@link Object#equals(Object)}. *
  • {@code false} in all other situations. *
* *

This assumes that any non-null objects passed to this function conform * to the {@code equals()} contract. */ public static boolean equal(@Nullable Object a, @Nullable Object b) { return a == b || (a != null && a.equals(b)); } /** * Generates a hash code for multiple values. The hash code is generated by * calling {@link Arrays#hashCode(Object[])}. * *

This is useful for implementing {@link Object#hashCode()}. For example, * in an object that has three properties, {@code x}, {@code y}, and * {@code z}, one could write: *

   * public int hashCode() {
   *   return Objects.hashCode(getX(), getY(), getZ());
   * }
* * Warning: When a single object is supplied, the returned hash code * does not equal the hash code of that object. */ public static int hashCode(Object... objects) { return Arrays.hashCode(objects); } } guice-3.0/core/src/com/google/inject/internal/util/Collections2.java0000644000175000017500000000315011461631440025364 0ustar drazzibdrazzib/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Collection; import java.util.Set; /** * Provides static methods for working with {@code Collection} instances. * * @author Chris Povirk * @author Mike Bostock * @author Jared Levy */ public final class Collections2 { private Collections2() {} /** * Converts an iterable into a collection. If the iterable is already a * collection, it is returned. Otherwise, an {@link java.util.ArrayList} is * created with the contents of the iterable in same iteration order. */ static Collection toCollection(Iterable iterable) { return (iterable instanceof Collection) ? (Collection) iterable : Lists.newArrayList(iterable); } static boolean setEquals(Set thisSet, @Nullable Object object) { if (object == thisSet) { return true; } if (object instanceof Set) { Set thatSet = (Set) object; return thisSet.size() == thatSet.size() && thisSet.containsAll(thatSet); } return false; } } guice-3.0/core/src/com/google/inject/internal/util/StackTraceElements.java0000644000175000017500000000503711526023460026552 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Member; import java.util.Map; /** * Creates stack trace elements for members. * * @author crazybob@google.com (Bob Lee) */ public class StackTraceElements { /*if[AOP]*/ static final Map, LineNumbers> lineNumbersCache = new MapMaker().weakKeys().softValues() .makeComputingMap(new Function, LineNumbers>() { public LineNumbers apply(Class key) { try { return new LineNumbers(key); } catch (IOException e) { throw new RuntimeException(e); } } }); /*end[AOP]*/ public static Object forMember(Member member) { if (member == null) { return SourceProvider.UNKNOWN_SOURCE; } Class declaringClass = member.getDeclaringClass(); /*if[AOP]*/ LineNumbers lineNumbers = lineNumbersCache.get(declaringClass); String fileName = lineNumbers.getSource(); Integer lineNumberOrNull = lineNumbers.getLineNumber(member); int lineNumber = lineNumberOrNull == null ? lineNumbers.getFirstLine() : lineNumberOrNull; /*end[AOP]*/ /*if[NO_AOP] String fileName = null; int lineNumber = -1; end[NO_AOP]*/ Class memberType = Classes.memberType(member); String memberName = memberType == Constructor.class ? "" : member.getName(); return new StackTraceElement(declaringClass.getName(), memberName, fileName, lineNumber); } public static Object forType(Class implementation) { /*if[AOP]*/ LineNumbers lineNumbers = lineNumbersCache.get(implementation); int lineNumber = lineNumbers.getFirstLine(); String fileName = lineNumbers.getSource(); /*end[AOP]*/ /*if[NO_AOP] String fileName = null; int lineNumber = -1; end[NO_AOP]*/ return new StackTraceElement(implementation.getName(), "class", fileName, lineNumber); } } guice-3.0/core/src/com/google/inject/internal/util/Strings.java0000644000175000017500000000353011460132776024466 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; /** * String utilities. * * @author crazybob@google.com (Bob Lee) */ public class Strings { private Strings() {} /** * Returns a string that is equivalent to the specified string with its * first character converted to uppercase as by {@link String#toUpperCase}. * The returned string will have the same value as the specified string if * its first character is non-alphabetic, if its first character is already * uppercase, or if the specified string is of length 0. * *

For example: *

   *    capitalize("foo bar").equals("Foo bar");
   *    capitalize("2b or not 2b").equals("2b or not 2b")
   *    capitalize("Foo bar").equals("Foo bar");
   *    capitalize("").equals("");
   * 
* * @param s the string whose first character is to be uppercased * @return a string equivalent to s with its first character * converted to uppercase * @throws NullPointerException if s is null */ public static String capitalize(String s) { if (s.length() == 0) { return s; } char first = s.charAt(0); char capitalized = Character.toUpperCase(first); return (first == capitalized) ? s : capitalized + s.substring(1); } } guice-3.0/core/src/com/google/inject/internal/util/AsynchronousComputationException.java0000644000175000017500000000161611460132776031635 0ustar drazzibdrazzib/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; /** * Wraps an exception that occured during a computation in a different thread. * * @author Bob Lee */ public class AsynchronousComputationException extends ComputationException { public AsynchronousComputationException(Throwable cause) { super(cause); } } guice-3.0/core/src/com/google/inject/internal/util/ImmutableList.java0000644000175000017500000005016711461631440025611 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.RandomAccess; /** * A high-performance, immutable, random-access {@code List} implementation. * Does not permit null elements. * *

Unlike {@link Collections#unmodifiableList}, which is a view of a * separate collection that can still change, an instance of {@code * ImmutableList} contains its own private data and will never change. * {@code ImmutableList} is convenient for {@code public static final} lists * ("constant lists") and also lets you easily make a "defensive copy" of a list * provided to your class by a caller. * *

Note: Although this class is not final, it cannot be subclassed as * it has no public or protected constructors. Thus, instances of this type are * guaranteed to be immutable. * * @see ImmutableMap * @see ImmutableSet * @author Kevin Bourrillion */ @SuppressWarnings("serial") // we're overriding default serialization public abstract class ImmutableList extends ImmutableCollection implements List, RandomAccess { private static final ImmutableList EMPTY_IMMUTABLE_LIST = new EmptyImmutableList(); /** * Returns the empty immutable list. This set behaves and performs comparably * to {@link Collections#emptyList}, and is preferable mainly for consistency * and maintainability of your code. */ // Casting to any type is safe because the list will never hold any elements. @SuppressWarnings("unchecked") public static ImmutableList of() { return (ImmutableList) EMPTY_IMMUTABLE_LIST; } /** * Returns an immutable list containing a single element. This list behaves * and performs comparably to {@link Collections#singleton}, but will not * accept a null element. It is preferable mainly for consistency and * maintainability of your code. * * @throws NullPointerException if {@code element} is null */ public static ImmutableList of(E element) { // TODO: evaluate a specialized SingletonImmutableList return new RegularImmutableList(copyIntoArray(element)); } // TODO: Add similar overloadings to ImmutableSet and ImmutableSortedSet /** * Returns an immutable list containing the given elements, in order. * * @throws NullPointerException if any element is null */ public static ImmutableList of(E e1, E e2) { return new RegularImmutableList(copyIntoArray(e1, e2)); } /** * Returns an immutable list containing the given elements, in order. * * @throws NullPointerException if any element is null */ public static ImmutableList of(E e1, E e2, E e3) { return new RegularImmutableList(copyIntoArray(e1, e2, e3)); } /** * Returns an immutable list containing the given elements, in order. * * @throws NullPointerException if any element is null */ public static ImmutableList of(E e1, E e2, E e3, E e4) { return new RegularImmutableList(copyIntoArray(e1, e2, e3, e4)); } /** * Returns an immutable list containing the given elements, in order. * * @throws NullPointerException if any element is null */ public static ImmutableList of(E e1, E e2, E e3, E e4, E e5) { return new RegularImmutableList(copyIntoArray(e1, e2, e3, e4, e5)); } /** * Returns an immutable list containing the given elements, in order. * * @throws NullPointerException if any of {@code elements} is null */ public static ImmutableList of(E... elements) { return (elements.length == 0) ? ImmutableList.of() : new RegularImmutableList(copyIntoArray(elements)); } /** * Returns an immutable list containing the given elements, in order. This * method iterates over {@code elements} at most once. Note that if {@code * list} is a {@code List}, then {@code ImmutableList.copyOf(list)} * returns an {@code ImmutableList} containing each of the strings * in {@code list}, while ImmutableList.of(list)} returns an {@code * ImmutableList>} containing one element (the given list * itself). * *

Note: Despite what the method name suggests, if {@code elements} * is an {@code ImmutableList}, no copy will actually be performed, and the * given list itself will be returned. * * @throws NullPointerException if any of {@code elements} is null */ public static ImmutableList copyOf(Iterable elements) { if (elements instanceof ImmutableList) { /* * TODO: If the given ImmutableList is a sublist, copy the referenced * portion of the array into a new array to save space? */ @SuppressWarnings("unchecked") // all supported methods are covariant ImmutableList list = (ImmutableList) elements; return list; } else if (elements instanceof Collection) { @SuppressWarnings("unchecked") Collection coll = (Collection) elements; return copyOfInternal(coll); } else { return copyOfInternal(Lists.newArrayList(elements)); } } /** * Returns an immutable list containing the given elements, in order. * * @throws NullPointerException if any of {@code elements} is null */ public static ImmutableList copyOf(Iterator elements) { return copyOfInternal(Lists.newArrayList(elements)); } private static ImmutableList copyOfInternal( ArrayList list) { return (list.isEmpty()) ? ImmutableList.of() : new RegularImmutableList(nullChecked(list.toArray())); } /** * Checks that all the array elements are non-null. * * @return the argument array * @throws NullPointerException if any element is null */ private static Object[] nullChecked(Object[] array) { for (int i = 0, len = array.length; i < len; i++) { if (array[i] == null) { throw new NullPointerException("at index " + i); } } return array; } private static ImmutableList copyOfInternal( Collection collection) { int size = collection.size(); return (size == 0) ? ImmutableList.of() : ImmutableList.createFromIterable(collection, size); } private ImmutableList() {} // This declaration is needed to make List.iterator() and // ImmutableCollection.iterator() consistent. @Override public abstract UnmodifiableIterator iterator(); // Mark these two methods with @Nullable public abstract int indexOf(@Nullable Object object); public abstract int lastIndexOf(@Nullable Object object); // constrain the return type to ImmutableList /** * Returns an immutable list of the elements between the specified {@code * fromIndex}, inclusive, and {@code toIndex}, exclusive. (If {@code * fromIndex} and {@code toIndex} are equal, the empty immutable list is * returned.) */ public abstract ImmutableList subList(int fromIndex, int toIndex); /** * Guaranteed to throw an exception and leave the list unmodified. * * @throws UnsupportedOperationException always */ public final boolean addAll(int index, Collection newElements) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the list unmodified. * * @throws UnsupportedOperationException always */ public final E set(int index, E element) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the list unmodified. * * @throws UnsupportedOperationException always */ public final void add(int index, E element) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the list unmodified. * * @throws UnsupportedOperationException always */ public final E remove(int index) { throw new UnsupportedOperationException(); } private static final class EmptyImmutableList extends ImmutableList { public int size() { return 0; } @Override public boolean isEmpty() { return true; } @Override public boolean contains(Object target) { return false; } @Override public UnmodifiableIterator iterator() { return Iterators.emptyIterator(); } private static final Object[] EMPTY_ARRAY = new Object[0]; @Override public Object[] toArray() { return EMPTY_ARRAY; } @Override public T[] toArray(T[] a) { if (a.length > 0) { a[0] = null; } return a; } public Object get(int index) { // guaranteed to fail, but at least we get a consistent message Preconditions.checkElementIndex(index, 0); throw new AssertionError("unreachable"); } @Override public int indexOf(Object target) { return -1; } @Override public int lastIndexOf(Object target) { return -1; } @Override public ImmutableList subList(int fromIndex, int toIndex) { Preconditions.checkPositionIndexes(fromIndex, toIndex, 0); return this; } public ListIterator listIterator() { return Iterators.emptyListIterator(); } public ListIterator listIterator(int start) { Preconditions.checkPositionIndex(start, 0); return Iterators.emptyListIterator(); } @Override public boolean containsAll(Collection targets) { return targets.isEmpty(); } @Override public boolean equals(@Nullable Object object) { if (object instanceof List) { List that = (List) object; return that.isEmpty(); } return false; } @Override public int hashCode() { return 1; } @Override public String toString() { return "[]"; } } private static final class RegularImmutableList extends ImmutableList { private final int offset; private final int size; private final Object[] array; private RegularImmutableList(Object[] array, int offset, int size) { this.offset = offset; this.size = size; this.array = array; } private RegularImmutableList(Object[] array) { this(array, 0, array.length); } public int size() { return size; } @Override public boolean isEmpty() { return false; } @Override public boolean contains(Object target) { return indexOf(target) != -1; } // The fake cast to E is safe because the creation methods only allow E's @SuppressWarnings("unchecked") @Override public UnmodifiableIterator iterator() { return (UnmodifiableIterator) Iterators.forArray(array, offset, size); } @Override public Object[] toArray() { Object[] newArray = new Object[size()]; System.arraycopy(array, offset, newArray, 0, size); return newArray; } @Override public T[] toArray(T[] other) { if (other.length < size) { other = ObjectArrays.newArray(other, size); } else if (other.length > size) { other[size] = null; } System.arraycopy(array, offset, other, 0, size); return other; } // The fake cast to E is safe because the creation methods only allow E's @SuppressWarnings("unchecked") public E get(int index) { Preconditions.checkElementIndex(index, size); return (E) array[index + offset]; } @Override public int indexOf(Object target) { if (target != null) { for (int i = offset; i < offset + size; i++) { if (array[i].equals(target)) { return i - offset; } } } return -1; } @Override public int lastIndexOf(Object target) { if (target != null) { for (int i = offset + size - 1; i >= offset; i--) { if (array[i].equals(target)) { return i - offset; } } } return -1; } @Override public ImmutableList subList(int fromIndex, int toIndex) { Preconditions.checkPositionIndexes(fromIndex, toIndex, size); return (fromIndex == toIndex) ? ImmutableList.of() : new RegularImmutableList( array, offset + fromIndex, toIndex - fromIndex); } public ListIterator listIterator() { return listIterator(0); } public ListIterator listIterator(final int start) { Preconditions.checkPositionIndex(start, size); return new ListIterator() { int index = start; public boolean hasNext() { return index < size; } public boolean hasPrevious() { return index > 0; } public int nextIndex() { return index; } public int previousIndex() { return index - 1; } public E next() { E result; try { result = get(index); } catch (IndexOutOfBoundsException rethrown) { throw new NoSuchElementException(); } index++; return result; } public E previous() { E result; try { result = get(index - 1); } catch (IndexOutOfBoundsException rethrown) { throw new NoSuchElementException(); } index--; return result; } public void set(E o) { throw new UnsupportedOperationException(); } public void add(E o) { throw new UnsupportedOperationException(); } public void remove() { throw new UnsupportedOperationException(); } }; } @Override public boolean equals(@Nullable Object object) { if (object == this) { return true; } if (!(object instanceof List)) { return false; } List that = (List) object; if (this.size() != that.size()) { return false; } int index = offset; if (object instanceof RegularImmutableList) { RegularImmutableList other = (RegularImmutableList) object; for (int i = other.offset; i < other.offset + other.size; i++) { if (!array[index++].equals(other.array[i])) { return false; } } } else { for (Object element : that) { if (!array[index++].equals(element)) { return false; } } } return true; } @Override public int hashCode() { // not caching hash code since it could change if the elements are mutable // in a way that modifies their hash codes int hashCode = 1; for (int i = offset; i < offset + size; i++) { hashCode = 31 * hashCode + array[i].hashCode(); } return hashCode; } @Override public String toString() { StringBuilder sb = new StringBuilder(size() * 16); sb.append('[').append(array[offset]); for (int i = offset + 1; i < offset + size; i++) { sb.append(", ").append(array[i]); } return sb.append(']').toString(); } } private static Object[] copyIntoArray(Object... source) { Object[] array = new Object[source.length]; int index = 0; for (Object element : source) { if (element == null) { throw new NullPointerException("at index " + index); } array[index++] = element; } return array; } private static ImmutableList createFromIterable( Iterable source, int estimatedSize) { Object[] array = new Object[estimatedSize]; int index = 0; for (Object element : source) { if (index == estimatedSize) { // At least one element was added after our call to size(). estimatedSize = ((estimatedSize / 2) + 1) * 3; array = copyOf(array, estimatedSize); } if (element == null) { throw new NullPointerException("at index " + index); } array[index++] = element; } if (index == 0) { return of(); } if (index != estimatedSize) { array = copyOf(array, index); } return new RegularImmutableList(array, 0, index); } // Avoid using Arrays.copyOf(), which is not present until JDK6. private static Object[] copyOf(Object[] oldArray, int newSize) { Object[] newArray = new Object[newSize]; System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize)); return newArray; } /* * Serializes ImmutableLists as their logical contents. This ensures that * implementation types do not leak into the serialized representation. */ private static class SerializedForm implements Serializable { final Object[] elements; SerializedForm(Object[] elements) { this.elements = elements; } Object readResolve() { return of(elements); } private static final long serialVersionUID = 0; } private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Use SerializedForm"); } @Override Object writeReplace() { return new SerializedForm(toArray()); } /** * Returns a new builder. The generated builder is equivalent to the builder * created by the {@link Builder} constructor. */ public static Builder builder() { return new Builder(); } /** * A builder for creating immutable list instances, especially * {@code public static final} lists ("constant lists"). * *

Example: *

{@code
   *   public static final ImmutableList GOOGLE_COLORS
   *       = new ImmutableList.Builder()
   *           .addAll(WEBSAFE_COLORS)
   *           .add(new Color(0, 191, 255))
   *           .build();}
* *

Builder instances can be reused - it is safe to call {@link #build} * multiple times to build multiple lists in series. Each new list * contains the one created before it. */ public static class Builder { private final ArrayList contents = Lists.newArrayList(); /** * Creates a new builder. The returned builder is equivalent to the builder * generated by {@link ImmutableList#builder}. */ public Builder() {} /** * Adds {@code element} to the {@code ImmutableList}. * * @param element the element to add * @return this {@code Builder} object * @throws NullPointerException if {@code element} is null */ public Builder add(E element) { Preconditions.checkNotNull(element, "element cannot be null"); contents.add(element); return this; } /** * Adds each element of {@code elements} to the {@code ImmutableList}. * * @param elements the {@code Iterable} to add to the {@code ImmutableList} * @return this {@code Builder} object * @throws NullPointerException if {@code elements} is or contains null */ public Builder addAll(Iterable elements) { if (elements instanceof Collection) { @SuppressWarnings("unchecked") Collection collection = (Collection) elements; contents.ensureCapacity(contents.size() + collection.size()); } for (E elem : elements) { Preconditions.checkNotNull(elem, "elements contains a null"); contents.add(elem); } return this; } /** * Returns a newly-created {@code ImmutableList} based on the contents of * the {@code Builder}. */ public ImmutableList build() { return copyOf(contents); } } } guice-3.0/core/src/com/google/inject/internal/util/MapMaker.java0000644000175000017500000010333211460132776024533 0ustar drazzibdrazzib/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import com.google.inject.internal.util.CustomConcurrentHashMap.ComputingStrategy; import com.google.inject.internal.util.CustomConcurrentHashMap.Internals; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.util.Map; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; /** * A {@link ConcurrentMap} builder, providing any combination of these * features: {@linkplain SoftReference soft} or {@linkplain WeakReference * weak} keys, soft or weak values, timed expiration, and on-demand * computation of values. Usage example:

 {@code
 *
 *   ConcurrentMap graphs = new MapMaker()
 *       .concurrencyLevel(32)
 *       .softKeys()
 *       .weakValues()
 *       .expiration(30, TimeUnit.MINUTES)
 *       .makeComputingMap(
 *           new Function() {
 *             public Graph apply(Key key) {
 *               return createExpensiveGraph(key);
 *             }
 *           });}
* * These features are all optional; {@code new MapMaker().makeMap()} * returns a valid concurrent map that behaves exactly like a * {@link ConcurrentHashMap}. * * The returned map is implemented as a hash table with similar performance * characteristics to {@link ConcurrentHashMap}. It supports all optional * operations of the {@code ConcurrentMap} interface. It does not permit * null keys or values. It is serializable; however, serializing a map that * uses soft or weak references can give unpredictable results. * *

Note: by default, the returned map uses equality comparisons * (the {@link Object#equals(Object) equals} method) to determine equality * for keys or values. However, if {@link #weakKeys()} or {@link * #softKeys()} was specified, the map uses identity ({@code ==}) * comparisons instead for keys. Likewise, if {@link #weakValues()} or * {@link #softValues()} was specified, the map uses identity comparisons * for values. * *

The returned map has weakly consistent iteration: an iterator * over one of the map's view collections may reflect some, all or none of * the changes made to the map after the iterator was created. * *

An entry whose key or value is reclaimed by the garbage collector * immediately disappears from the map. (If the default settings of strong * keys and strong values are used, this will never happen.) The client can * never observe a partially-reclaimed entry. Any {@link java.util.Map.Entry} * instance retrieved from the map's {@linkplain Map#entrySet() entry set} * is snapshot of that entry's state at the time of retrieval. * *

{@code new MapMaker().weakKeys().makeMap()} can almost always be * used as a drop-in replacement for {@link java.util.WeakHashMap}, adding * concurrency, asynchronous cleanup, identity-based equality for keys, and * great flexibility. * * @author Bob Lee * @author Kevin Bourrillion */ public final class MapMaker { private Strength keyStrength = Strength.STRONG; private Strength valueStrength = Strength.STRONG; private long expirationNanos = 0; private boolean useCustomMap; private final CustomConcurrentHashMap.Builder builder = new CustomConcurrentHashMap.Builder(); /** * Constructs a new {@code MapMaker} instance with default settings, * including strong keys, strong values, and no automatic expiration. */ public MapMaker() {} /** * Sets a custom initial capacity (defaults to 16). Resizing this or * any other kind of hash table is a relatively slow operation, so, * when possible, it is a good idea to provide estimates of expected * table sizes. * * @throws IllegalArgumentException if {@code initialCapacity} is * negative * @throws IllegalStateException if an initial capacity was already set * (TODO: make that true) */ public MapMaker initialCapacity(int initialCapacity) { builder.initialCapacity(initialCapacity); return this; } /** * Sets a custom load factor (defaults to 0.75). * * @throws IllegalArgumentException if {@code loadFactor} is * nonpositive * @throws IllegalStateException if a load factor was already set * (TODO: make that true) */ public MapMaker loadFactor(float loadFactor) { builder.loadFactor(loadFactor); return this; } /** * Guides the allowed concurrency among update operations. Used as a * hint for internal sizing. The table is internally partitioned to try * to permit the indicated number of concurrent updates without * contention. Because placement in hash tables is essentially random, * the actual concurrency will vary. Ideally, you should choose a value * to accommodate as many threads as will ever concurrently modify the * table. Using a significantly higher value than you need can waste * space and time, and a significantly lower value can lead to thread * contention. But overestimates and underestimates within an order of * magnitude do not usually have much noticeable impact. A value of one * is appropriate when it is known that only one thread will modify and * all others will only read. Defaults to 16. * * @throws IllegalArgumentException if {@code concurrencyLevel} is * nonpositive * @throws IllegalStateException if a concurrency level was already set * (TODO: make that true) */ public MapMaker concurrencyLevel(int concurrencyLevel) { builder.concurrencyLevel(concurrencyLevel); return this; } /** * Specifies that each key (not value) stored in the map should be * wrapped in a {@link WeakReference} (by default, strong references * are used). * * @throws IllegalStateException if the key strength was already set */ public MapMaker weakKeys() { return setKeyStrength(Strength.WEAK); } /** * Specifies that each key (not value) stored in the map should be * wrapped in a {@link SoftReference} (by default, strong references * are used). * * @throws IllegalStateException if the key strength was already set */ public MapMaker softKeys() { return setKeyStrength(Strength.SOFT); } private MapMaker setKeyStrength(Strength strength) { if (keyStrength != Strength.STRONG) { throw new IllegalStateException("Key strength was already set to " + keyStrength + "."); } keyStrength = strength; useCustomMap = true; return this; } /** * Specifies that each value (not key) stored in the map should be * wrapped in a {@link WeakReference} (by default, strong references * are used). * * @throws IllegalStateException if the key strength was already set */ public MapMaker weakValues() { return setValueStrength(Strength.WEAK); } /** * Specifies that each value (not key) stored in the map should be * wrapped in a {@link SoftReference} (by default, strong references * are used). * * @throws IllegalStateException if the value strength was already set */ public MapMaker softValues() { return setValueStrength(Strength.SOFT); } private MapMaker setValueStrength(Strength strength) { if (valueStrength != Strength.STRONG) { throw new IllegalStateException("Value strength was already set to " + valueStrength + "."); } valueStrength = strength; useCustomMap = true; return this; } /** * Specifies that each entry should be automatically removed from the * map once a fixed duration has passed since the entry's creation. * * @param duration the length of time after an entry is created that it * should be automatically removed * @param unit the unit that {@code duration} is expressed in * @throws IllegalArgumentException if {@code duration} is not positive * @throws IllegalStateException if the expiration time was already set */ public MapMaker expiration(long duration, TimeUnit unit) { if (expirationNanos != 0) { throw new IllegalStateException("expiration time of " + expirationNanos + " ns was already set"); } if (duration <= 0) { throw new IllegalArgumentException("invalid duration: " + duration); } this.expirationNanos = unit.toNanos(duration); useCustomMap = true; return this; } /** * Builds the final map, without on-demand computation of values. * * @param the type of keys to be stored in the returned map * @param the type of values to be stored in the returned map * @return a concurrent map having the requested features */ public ConcurrentMap makeMap() { return useCustomMap ? new StrategyImpl(this).map : new ConcurrentHashMap(builder.initialCapacity, builder.loadFactor, builder.concurrencyLevel); } /** * Builds a map that supports atomic, on-demand computation of values. {@link * Map#get} returns the value corresponding to the given key, atomically * computes it using the computer function passed to this builder, or waits * for another thread to compute the value if necessary. Only one value will * be computed for each key at a given time. * *

If an entry's value has not finished computing yet, query methods * besides {@link java.util.Map#get} return immediately as if an entry doesn't * exist. In other words, an entry isn't externally visible until the value's * computation completes. * *

{@link Map#get} in the returned map implementation throws: * *

    *
  • {@link NullPointerException} if the key is null or the computer returns * null
  • *
  • or {@link ComputationException} wrapping an exception thrown by the * computation
  • *
* *

Note: Callers of {@code get()} must ensure that the key * argument is of type {@code K}. {@code Map.get()} takes {@code Object}, so * the key type is not checked at compile time. Passing an object of a type * other than {@code K} can result in that object being unsafely passed to the * computer function as type {@code K} not to mention the unsafe key being * stored in the map. * *

If {@link java.util.Map#put} is called before a computation completes, * other threads waiting on the computation will wake up and return the put * value up until the computation completes, at which point the computation * result will overwrite the value from the {@code put} in the map. */ public ConcurrentMap makeComputingMap( Function computer) { return new StrategyImpl(this, computer).map; } // Remainder of this file is private implementation details private enum Strength { WEAK { boolean equal(Object a, Object b) { return a == b; } int hash(Object o) { return System.identityHashCode(o); } ValueReference referenceValue( ReferenceEntry entry, V value) { return new WeakValueReference(value, entry); } ReferenceEntry newEntry( Internals> internals, K key, int hash, ReferenceEntry next) { return (next == null) ? new WeakEntry(internals, key, hash) : new LinkedWeakEntry(internals, key, hash, next); } ReferenceEntry copyEntry( K key, ReferenceEntry original, ReferenceEntry newNext) { WeakEntry from = (WeakEntry) original; return (newNext == null) ? new WeakEntry(from.internals, key, from.hash) : new LinkedWeakEntry( from.internals, key, from.hash, newNext); } }, SOFT { boolean equal(Object a, Object b) { return a == b; } int hash(Object o) { return System.identityHashCode(o); } ValueReference referenceValue( ReferenceEntry entry, V value) { return new SoftValueReference(value, entry); } ReferenceEntry newEntry( Internals> internals, K key, int hash, ReferenceEntry next) { return (next == null) ? new SoftEntry(internals, key, hash) : new LinkedSoftEntry(internals, key, hash, next); } ReferenceEntry copyEntry( K key, ReferenceEntry original, ReferenceEntry newNext) { SoftEntry from = (SoftEntry) original; return (newNext == null) ? new SoftEntry(from.internals, key, from.hash) : new LinkedSoftEntry( from.internals, key, from.hash, newNext); } }, STRONG { boolean equal(Object a, Object b) { return a.equals(b); } int hash(Object o) { return o.hashCode(); } ValueReference referenceValue( ReferenceEntry entry, V value) { return new StrongValueReference(value); } ReferenceEntry newEntry( Internals> internals, K key, int hash, ReferenceEntry next) { return (next == null) ? new StrongEntry(internals, key, hash) : new LinkedStrongEntry( internals, key, hash, next); } ReferenceEntry copyEntry( K key, ReferenceEntry original, ReferenceEntry newNext) { StrongEntry from = (StrongEntry) original; return (newNext == null) ? new StrongEntry(from.internals, key, from.hash) : new LinkedStrongEntry( from.internals, key, from.hash, newNext); } }; /** * Determines if two keys or values are equal according to this * strength strategy. */ abstract boolean equal(Object a, Object b); /** * Hashes a key according to this strategy. */ abstract int hash(Object o); /** * Creates a reference for the given value according to this value * strength. */ abstract ValueReference referenceValue( ReferenceEntry entry, V value); /** * Creates a new entry based on the current key strength. */ abstract ReferenceEntry newEntry( Internals> internals, K key, int hash, ReferenceEntry next); /** * Creates a new entry and copies the value and other state from an * existing entry. */ abstract ReferenceEntry copyEntry(K key, ReferenceEntry original, ReferenceEntry newNext); } private static class StrategyImpl implements Serializable, ComputingStrategy> { final Strength keyStrength; final Strength valueStrength; final ConcurrentMap map; final long expirationNanos; Internals> internals; StrategyImpl(MapMaker maker) { this.keyStrength = maker.keyStrength; this.valueStrength = maker.valueStrength; this.expirationNanos = maker.expirationNanos; map = maker.builder.buildMap(this); } StrategyImpl( MapMaker maker, Function computer) { this.keyStrength = maker.keyStrength; this.valueStrength = maker.valueStrength; this.expirationNanos = maker.expirationNanos; map = maker.builder.buildComputingMap(this, computer); } public void setValue(ReferenceEntry entry, V value) { setValueReference( entry, valueStrength.referenceValue(entry, value)); if (expirationNanos > 0) { scheduleRemoval(entry.getKey(), value); } } void scheduleRemoval(K key, V value) { /* * TODO: Keep weak reference to map, too. Build a priority * queue out of the entries themselves instead of creating a * task per entry. Then, we could have one recurring task per * map (which would clean the entire map and then reschedule * itself depending upon when the next expiration comes). We * also want to avoid removing an entry prematurely if the * entry was set to the same value again. */ final WeakReference keyReference = new WeakReference(key); final WeakReference valueReference = new WeakReference(value); ExpirationTimer.instance.schedule( new TimerTask() { public void run() { K key = keyReference.get(); if (key != null) { // Remove if the value is still the same. map.remove(key, valueReference.get()); } } }, TimeUnit.NANOSECONDS.toMillis(expirationNanos)); } public boolean equalKeys(K a, Object b) { return keyStrength.equal(a, b); } public boolean equalValues(V a, Object b) { return valueStrength.equal(a, b); } public int hashKey(Object key) { return keyStrength.hash(key); } public K getKey(ReferenceEntry entry) { return entry.getKey(); } public int getHash(ReferenceEntry entry) { return entry.getHash(); } public ReferenceEntry newEntry( K key, int hash, ReferenceEntry next) { return keyStrength.newEntry(internals, key, hash, next); } public ReferenceEntry copyEntry(K key, ReferenceEntry original, ReferenceEntry newNext) { ValueReference valueReference = original.getValueReference(); if (valueReference == COMPUTING) { ReferenceEntry newEntry = newEntry(key, original.getHash(), newNext); newEntry.setValueReference( new FutureValueReference(original, newEntry)); return newEntry; } else { ReferenceEntry newEntry = newEntry(key, original.getHash(), newNext); newEntry.setValueReference(valueReference.copyFor(newEntry)); return newEntry; } } /** * Waits for a computation to complete. Returns the result of the * computation or null if none was available. */ public V waitForValue(ReferenceEntry entry) throws InterruptedException { ValueReference valueReference = entry.getValueReference(); if (valueReference == COMPUTING) { synchronized (entry) { while ((valueReference = entry.getValueReference()) == COMPUTING) { entry.wait(); } } } return valueReference.waitForValue(); } /** * Used by CustomConcurrentHashMap to retrieve values. Returns null * instead of blocking or throwing an exception. */ public V getValue(ReferenceEntry entry) { ValueReference valueReference = entry.getValueReference(); return valueReference.get(); } public V compute(K key, final ReferenceEntry entry, Function computer) { V value; try { value = computer.apply(key); } catch (Throwable t) { setValueReference( entry, new ComputationExceptionReference(t)); throw new ComputationException(t); } if (value == null) { String message = computer + " returned null for key " + key + "."; setValueReference( entry, new NullOutputExceptionReference(message)); throw new NullOutputException(message); } else { setValue(entry, value); } return value; } /** * Sets the value reference on an entry and notifies waiting * threads. */ void setValueReference(ReferenceEntry entry, ValueReference valueReference) { boolean notifyOthers = (entry.getValueReference() == COMPUTING); entry.setValueReference(valueReference); if (notifyOthers) { synchronized (entry) { entry.notifyAll(); } } } /** * Points to an old entry where a value is being computed. Used to * support non-blocking copying of entries during table expansion, * removals, etc. */ private class FutureValueReference implements ValueReference { final ReferenceEntry original; final ReferenceEntry newEntry; FutureValueReference( ReferenceEntry original, ReferenceEntry newEntry) { this.original = original; this.newEntry = newEntry; } public V get() { boolean success = false; try { V value = original.getValueReference().get(); success = true; return value; } finally { if (!success) { removeEntry(); } } } public ValueReference copyFor(ReferenceEntry entry) { return new FutureValueReference(original, entry); } public V waitForValue() throws InterruptedException { boolean success = false; try { // assert that key != null V value = StrategyImpl.this.waitForValue(original); success = true; return value; } finally { if (!success) { removeEntry(); } } } /** * Removes the entry in the event of an exception. Ideally, * we'd clean up as soon as the computation completes, but we * can't do that without keeping a reference to this entry from * the original. */ void removeEntry() { internals.removeEntry(newEntry); } } public ReferenceEntry getNext( ReferenceEntry entry) { return entry.getNext(); } public void setInternals( Internals> internals) { this.internals = internals; } private static final long serialVersionUID = 0; private void writeObject(ObjectOutputStream out) throws IOException { // Custom serialization code ensures that the key and value // strengths are written before the map. We'll need them to // deserialize the map entries. out.writeObject(keyStrength); out.writeObject(valueStrength); out.writeLong(expirationNanos); // TODO: It is possible for the strategy to try to use the map // or internals during deserialization, for example, if an // entry gets reclaimed. We could detect this case and queue up // removals to be flushed after we deserialize the map. out.writeObject(internals); out.writeObject(map); } /** * Fields used during deserialization. We use a nested class so we * don't load them until we need them. We need to use reflection to * set final fields outside of the constructor. */ private static class Fields { static final Field keyStrength = findField("keyStrength"); static final Field valueStrength = findField("valueStrength"); static final Field expirationNanos = findField("expirationNanos"); static final Field internals = findField("internals"); static final Field map = findField("map"); static Field findField(String name) { try { Field f = StrategyImpl.class.getDeclaredField(name); f.setAccessible(true); return f; } catch (NoSuchFieldException e) { throw new AssertionError(e); } } } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { try { Fields.keyStrength.set(this, in.readObject()); Fields.valueStrength.set(this, in.readObject()); Fields.expirationNanos.set(this, in.readLong()); Fields.internals.set(this, in.readObject()); Fields.map.set(this, in.readObject()); } catch (IllegalAccessException e) { throw new AssertionError(e); } } } /** A reference to a value. */ private interface ValueReference { /** * Gets the value. Does not block or throw exceptions. */ V get(); /** Creates a copy of this reference for the given entry. */ ValueReference copyFor(ReferenceEntry entry); /** * Waits for a value that may still be computing. Unlike get(), * this method can block (in the case of FutureValueReference) or * throw an exception. */ V waitForValue() throws InterruptedException; } private static final ValueReference COMPUTING = new ValueReference() { public Object get() { return null; } public ValueReference copyFor( ReferenceEntry entry) { throw new AssertionError(); } public Object waitForValue() { throw new AssertionError(); } }; /** * Singleton placeholder that indicates a value is being computed. */ @SuppressWarnings("unchecked") // Safe because impl never uses a parameter or returns any non-null value private static ValueReference computing() { return (ValueReference) COMPUTING; } /** Used to provide null output exceptions to other threads. */ private static class NullOutputExceptionReference implements ValueReference { final String message; NullOutputExceptionReference(String message) { this.message = message; } public V get() { return null; } public ValueReference copyFor( ReferenceEntry entry) { return this; } public V waitForValue() { throw new NullOutputException(message); } } /** Used to provide computation exceptions to other threads. */ private static class ComputationExceptionReference implements ValueReference { final Throwable t; ComputationExceptionReference(Throwable t) { this.t = t; } public V get() { return null; } public ValueReference copyFor( ReferenceEntry entry) { return this; } public V waitForValue() { throw new AsynchronousComputationException(t); } } /** Wrapper class ensures that queue isn't created until it's used. */ private static class QueueHolder { static final FinalizableReferenceQueue queue = new FinalizableReferenceQueue(); } /** * An entry in a reference map. */ private interface ReferenceEntry { /** * Gets the value reference from this entry. */ ValueReference getValueReference(); /** * Sets the value reference for this entry. * * @param valueReference */ void setValueReference(ValueReference valueReference); /** * Removes this entry from the map if its value reference hasn't * changed. Used to clean up after values. The value reference can * just call this method on the entry so it doesn't have to keep * its own reference to the map. */ void valueReclaimed(); /** Gets the next entry in the chain. */ ReferenceEntry getNext(); /** Gets the entry's hash. */ int getHash(); /** Gets the key for this entry. */ public K getKey(); } /** * Used for strongly-referenced keys. */ private static class StrongEntry implements ReferenceEntry { final K key; StrongEntry(Internals> internals, K key, int hash) { this.internals = internals; this.key = key; this.hash = hash; } public K getKey() { return this.key; } // The code below is exactly the same for each entry type. final Internals> internals; final int hash; volatile ValueReference valueReference = computing(); public ValueReference getValueReference() { return valueReference; } public void setValueReference( ValueReference valueReference) { this.valueReference = valueReference; } public void valueReclaimed() { internals.removeEntry(this, null); } public ReferenceEntry getNext() { return null; } public int getHash() { return hash; } } private static class LinkedStrongEntry extends StrongEntry { LinkedStrongEntry(Internals> internals, K key, int hash, ReferenceEntry next) { super(internals, key, hash); this.next = next; } final ReferenceEntry next; @Override public ReferenceEntry getNext() { return next; } } /** * Used for softly-referenced keys. */ private static class SoftEntry extends FinalizableSoftReference implements ReferenceEntry { SoftEntry(Internals> internals, K key, int hash) { super(key, QueueHolder.queue); this.internals = internals; this.hash = hash; } public K getKey() { return get(); } public void finalizeReferent() { internals.removeEntry(this); } // The code below is exactly the same for each entry type. final Internals> internals; final int hash; volatile ValueReference valueReference = computing(); public ValueReference getValueReference() { return valueReference; } public void setValueReference( ValueReference valueReference) { this.valueReference = valueReference; } public void valueReclaimed() { internals.removeEntry(this, null); } public ReferenceEntry getNext() { return null; } public int getHash() { return hash; } } private static class LinkedSoftEntry extends SoftEntry { LinkedSoftEntry(Internals> internals, K key, int hash, ReferenceEntry next) { super(internals, key, hash); this.next = next; } final ReferenceEntry next; @Override public ReferenceEntry getNext() { return next; } } /** * Used for weakly-referenced keys. */ private static class WeakEntry extends FinalizableWeakReference implements ReferenceEntry { WeakEntry(Internals> internals, K key, int hash) { super(key, QueueHolder.queue); this.internals = internals; this.hash = hash; } public K getKey() { return get(); } public void finalizeReferent() { internals.removeEntry(this); } // The code below is exactly the same for each entry type. final Internals> internals; final int hash; volatile ValueReference valueReference = computing(); public ValueReference getValueReference() { return valueReference; } public void setValueReference( ValueReference valueReference) { this.valueReference = valueReference; } public void valueReclaimed() { internals.removeEntry(this, null); } public ReferenceEntry getNext() { return null; } public int getHash() { return hash; } } private static class LinkedWeakEntry extends WeakEntry { LinkedWeakEntry(Internals> internals, K key, int hash, ReferenceEntry next) { super(internals, key, hash); this.next = next; } final ReferenceEntry next; @Override public ReferenceEntry getNext() { return next; } } /** References a weak value. */ private static class WeakValueReference extends FinalizableWeakReference implements ValueReference { final ReferenceEntry entry; WeakValueReference(V referent, ReferenceEntry entry) { super(referent, QueueHolder.queue); this.entry = entry; } public void finalizeReferent() { entry.valueReclaimed(); } public ValueReference copyFor( ReferenceEntry entry) { return new WeakValueReference(get(), entry); } public V waitForValue() throws InterruptedException { return get(); } } /** References a soft value. */ private static class SoftValueReference extends FinalizableSoftReference implements ValueReference { final ReferenceEntry entry; SoftValueReference(V referent, ReferenceEntry entry) { super(referent, QueueHolder.queue); this.entry = entry; } public void finalizeReferent() { entry.valueReclaimed(); } public ValueReference copyFor( ReferenceEntry entry) { return new SoftValueReference(get(), entry); } public V waitForValue() { return get(); } } /** References a strong value. */ private static class StrongValueReference implements ValueReference { final V referent; StrongValueReference(V referent) { this.referent = referent; } public V get() { return referent; } public ValueReference copyFor( ReferenceEntry entry) { return this; } public V waitForValue() { return get(); } } } guice-3.0/core/src/com/google/inject/internal/util/ImmutableMap.java0000644000175000017500000005653311461631440025416 0ustar drazzibdrazzib/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.Serializable; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentMap; /** * An immutable, hash-based {@link Map} with reliable user-specified iteration * order. Does not permit null keys or values. * *

Unlike {@link Collections#unmodifiableMap}, which is a view of a * separate map which can still change, an instance of {@code ImmutableMap} * contains its own data and will never change. {@code ImmutableMap} is * convenient for {@code public static final} maps ("constant maps") and also * lets you easily make a "defensive copy" of a map provided to your class by a * caller. * *

Note: Although this class is not final, it cannot be subclassed as * it has no public or protected constructors. Thus, instances of this class are * guaranteed to be immutable. * * @see ImmutableList * @see ImmutableSet * @author Jesse Wilson * @author Kevin Bourrillion */ @SuppressWarnings("serial") // we're overriding default serialization public abstract class ImmutableMap implements ConcurrentMap, Serializable { private static final ImmutableMap EMPTY_IMMUTABLE_MAP = new EmptyImmutableMap(); // TODO: restore prebuilder API? optimize, compare performance to HashMap /** * Returns the empty map. This map behaves and performs comparably to * {@link Collections#emptyMap}, and is preferable mainly for consistency * and maintainability of your code. */ // Casting to any type is safe because the set will never hold any elements. @SuppressWarnings("unchecked") public static ImmutableMap of() { return (ImmutableMap) EMPTY_IMMUTABLE_MAP; } /** * Returns an immutable map containing a single entry. This map behaves and * performs comparably to {@link Collections#singletonMap} but will not accept * a null key or value. It is preferable mainly for consistency and * maintainability of your code. */ public static ImmutableMap of(K k1, V v1) { return new SingletonImmutableMap( Preconditions.checkNotNull(k1), Preconditions.checkNotNull(v1)); } /** * Returns an immutable map containing the given entries, in order. * * @throws IllegalArgumentException if duplicate keys are added */ public static ImmutableMap of(K k1, V v1, K k2, V v2) { return new RegularImmutableMap(entryOf(k1, v1), entryOf(k2, v2)); } /** * Returns an immutable map containing the given entries, in order. * * @throws IllegalArgumentException if duplicate keys are added */ public static ImmutableMap of( K k1, V v1, K k2, V v2, K k3, V v3) { return new RegularImmutableMap( entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3)); } /** * Returns an immutable map containing the given entries, in order. * * @throws IllegalArgumentException if duplicate keys are added */ public static ImmutableMap of( K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { return new RegularImmutableMap( entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4)); } /** * Returns an immutable map containing the given entries, in order. * * @throws IllegalArgumentException if duplicate keys are added */ public static ImmutableMap of( K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { return new RegularImmutableMap(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5)); } // looking for of() with > 5 entries? Use the builder instead. /** * Returns a new builder. The generated builder is equivalent to the builder * created by the {@link Builder} constructor. */ public static Builder builder() { return new Builder(); } /** * Verifies that {@code key} and {@code value} are non-null, and returns a new * entry with those values. */ private static Entry entryOf(K key, V value) { return Maps.immutableEntry(Preconditions.checkNotNull(key), Preconditions.checkNotNull(value)); } /** * A builder for creating immutable map instances, especially {@code public * static final} maps ("constant maps"). Example:

   {@code
   *
   *   static final ImmutableMap WORD_TO_INT =
   *       new ImmutableMap.Builder()
   *           .put("one", 1)
   *           .put("two", 2)
   *           .put("three", 3)
   *           .build();}
* * For small immutable maps, the {@code ImmutableMap.of()} methods are * even more convenient. * *

Builder instances can be reused - it is safe to call {@link #build} * multiple times to build multiple maps in series. Each map is a superset of * the maps created before it. */ public static class Builder { final List> entries = Lists.newArrayList(); /** * Creates a new builder. The returned builder is equivalent to the builder * generated by {@link ImmutableMap#builder}. */ public Builder() {} /** * Associates {@code key} with {@code value} in the built map. Duplicate * keys are not allowed, and will cause {@link #build} to fail. */ public Builder put(K key, V value) { entries.add(entryOf(key, value)); return this; } /** * Associates all of {@code map's} keys and values in the built map. * Duplicate keys are not allowed, and will cause {@link #build} to fail. * * @throws NullPointerException if any key or value in {@code map} is null */ public Builder putAll(Map map) { for (Entry entry : map.entrySet()) { put(entry.getKey(), entry.getValue()); } return this; } // TODO: Should build() and the ImmutableBiMap version throw an // IllegalStateException instead? /** * Returns a newly-created immutable map. * * @throws IllegalArgumentException if duplicate keys were added */ public ImmutableMap build() { return fromEntryList(entries); } private static ImmutableMap fromEntryList( List> entries) { int size = entries.size(); switch (size) { case 0: return of(); case 1: return new SingletonImmutableMap(Iterables.getOnlyElement(entries)); default: Entry[] entryArray = entries.toArray(new Entry[entries.size()]); return new RegularImmutableMap(entryArray); } } } /** * Returns an immutable map containing the same entries as {@code map}. If * {@code map} somehow contains entries with duplicate keys (for example, if * it is a {@code SortedMap} whose comparator is not consistent with * equals), the results of this method are undefined. * *

Note: Despite what the method name suggests, if {@code map} is an * {@code ImmutableMap}, no copy will actually be performed, and the given map * itself will be returned. * * @throws NullPointerException if any key or value in {@code map} is null */ public static ImmutableMap copyOf( Map map) { if (map instanceof ImmutableMap) { @SuppressWarnings("unchecked") // safe since map is not writable ImmutableMap kvMap = (ImmutableMap) map; return kvMap; } int size = map.size(); switch (size) { case 0: return of(); case 1: Map.Entry loneEntry = Iterables.getOnlyElement(map.entrySet()); /* * Must cast next line to (K) and (V) to avoid returning an * ImmutableMap, which is incompatible * with the return type ImmutableMap. (Eclipse will complain * mightily about this line if there's no cast.) */ return of((K) loneEntry.getKey(), (V) loneEntry.getValue()); default: Entry[] array = new Entry[size]; int i = 0; for (Entry entry : map.entrySet()) { /* * See comment above re: to . */ array[i++] = entryOf((K) entry.getKey(), (V) entry.getValue()); } return new RegularImmutableMap(array); } } ImmutableMap() {} /** * Guaranteed to throw an exception and leave the map unmodified. * * @throws UnsupportedOperationException always */ public final V put(K k, V v) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the map unmodified. * * @throws UnsupportedOperationException always */ public final V remove(Object o) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the map unmodified. * * @throws UnsupportedOperationException always */ public final V putIfAbsent(K key, V value) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the map unmodified. * * @throws UnsupportedOperationException always */ public final boolean remove(Object key, Object value) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the map unmodified. * * @throws UnsupportedOperationException always */ public final boolean replace(K key, V oldValue, V newValue) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the map unmodified. * * @throws UnsupportedOperationException always */ public final V replace(K key, V value) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the map unmodified. * * @throws UnsupportedOperationException always */ public final void putAll(Map map) { throw new UnsupportedOperationException(); } /** * Guaranteed to throw an exception and leave the map unmodified. * * @throws UnsupportedOperationException always */ public final void clear() { throw new UnsupportedOperationException(); } // Overriding to mark it Nullable public abstract boolean containsKey(@Nullable Object key); // Overriding to mark it Nullable public abstract boolean containsValue(@Nullable Object value); // Overriding to mark it Nullable public abstract V get(@Nullable Object key); /** * Returns an immutable set of the mappings in this map. The entries are in * the same order as the parameters used to build this map. */ public abstract ImmutableSet> entrySet(); /** * Returns an immutable set of the keys in this map. These keys are in * the same order as the parameters used to build this map. */ public abstract ImmutableSet keySet(); /** * Returns an immutable collection of the values in this map. The values are * in the same order as the parameters used to build this map. */ public abstract ImmutableCollection values(); @Override public boolean equals(@Nullable Object object) { if (object == this) { return true; } if (object instanceof Map) { Map that = (Map) object; return this.entrySet().equals(that.entrySet()); } return false; } @Override public int hashCode() { // not caching hash code since it could change if map values are mutable // in a way that modifies their hash codes return entrySet().hashCode(); } @Override public String toString() { StringBuilder result = new StringBuilder(size() * 16).append('{'); Iterator> entries = entrySet().iterator(); result.append(entries.next()); while (entries.hasNext()) { result.append(", ").append(entries.next()); } return result.append('}').toString(); } private static final class EmptyImmutableMap extends ImmutableMap { @Override public Object get(Object key) { return null; } public int size() { return 0; } public boolean isEmpty() { return true; } @Override public boolean containsKey(Object key) { return false; } @Override public boolean containsValue(Object value) { return false; } @Override public ImmutableSet> entrySet() { return ImmutableSet.of(); } @Override public ImmutableSet keySet() { return ImmutableSet.of(); } @Override public ImmutableCollection values() { return ImmutableCollection.EMPTY_IMMUTABLE_COLLECTION; } @Override public boolean equals(@Nullable Object object) { if (object instanceof Map) { Map that = (Map) object; return that.isEmpty(); } return false; } @Override public int hashCode() { return 0; } @Override public String toString() { return "{}"; } } private static final class SingletonImmutableMap extends ImmutableMap { private transient final K singleKey; private transient final V singleValue; private transient Entry entry; private SingletonImmutableMap(K singleKey, V singleValue) { this.singleKey = singleKey; this.singleValue = singleValue; } private SingletonImmutableMap(Entry entry) { this.entry = entry; this.singleKey = entry.getKey(); this.singleValue = entry.getValue(); } private Entry entry() { Entry e = entry; return (e == null) ? (entry = Maps.immutableEntry(singleKey, singleValue)) : e; } @Override public V get(Object key) { return singleKey.equals(key) ? singleValue : null; } public int size() { return 1; } public boolean isEmpty() { return false; } @Override public boolean containsKey(Object key) { return singleKey.equals(key); } @Override public boolean containsValue(Object value) { return singleValue.equals(value); } private transient ImmutableSet> entrySet; @Override public ImmutableSet> entrySet() { ImmutableSet> es = entrySet; return (es == null) ? (entrySet = ImmutableSet.of(entry())) : es; } private transient ImmutableSet keySet; @Override public ImmutableSet keySet() { ImmutableSet ks = keySet; return (ks == null) ? (keySet = ImmutableSet.of(singleKey)) : ks; } private transient ImmutableCollection values; @Override public ImmutableCollection values() { ImmutableCollection v = values; return (v == null) ? (values = new Values(singleValue)) : v; } private static class Values extends ImmutableCollection { final V singleValue; Values(V singleValue) { this.singleValue = singleValue; } @Override public boolean contains(Object object) { return singleValue.equals(object); } @Override public boolean isEmpty() { return false; } public int size() { return 1; } @Override public UnmodifiableIterator iterator() { return Iterators.singletonIterator(singleValue); } } @Override public boolean equals(@Nullable Object object) { if (object == this) { return true; } if (object instanceof Map) { Map that = (Map) object; if (that.size() != 1) { return false; } Map.Entry entry = that.entrySet().iterator().next(); return singleKey.equals(entry.getKey()) && singleValue.equals(entry.getValue()); } return false; } @Override public int hashCode() { return singleKey.hashCode() ^ singleValue.hashCode(); } @Override public String toString() { return new StringBuilder() .append('{') .append(singleKey.toString()) .append('=') .append(singleValue.toString()) .append('}') .toString(); } } private static final class RegularImmutableMap extends ImmutableMap { private transient final Entry[] entries; // entries in insertion order private transient final Object[] table; // alternating keys and values // 'and' with an int then shift to get a table index private transient final int mask; private transient final int keySetHashCode; private RegularImmutableMap(Entry... entries) { // each of our 6 callers carefully put only Entrys into the array! @SuppressWarnings("unchecked") Entry[] tmp = (Entry[]) entries; this.entries = tmp; int tableSize = Hashing.chooseTableSize(entries.length); table = new Object[tableSize * 2]; mask = tableSize - 1; int keySetHashCodeMutable = 0; for (Entry entry : this.entries) { K key = entry.getKey(); int keyHashCode = key.hashCode(); for (int i = Hashing.smear(keyHashCode); true; i++) { int index = (i & mask) * 2; Object existing = table[index]; if (existing == null) { V value = entry.getValue(); table[index] = key; table[index + 1] = value; keySetHashCodeMutable += keyHashCode; break; } else if (existing.equals(key)) { throw new IllegalArgumentException("duplicate key: " + key); } } } keySetHashCode = keySetHashCodeMutable; } @Override public V get(Object key) { if (key == null) { return null; } for (int i = Hashing.smear(key.hashCode()); true; i++) { int index = (i & mask) * 2; Object candidate = table[index]; if (candidate == null) { return null; } if (candidate.equals(key)) { // we're careful to store only V's at odd indices @SuppressWarnings("unchecked") V value = (V) table[index + 1]; return value; } } } public int size() { return entries.length; } public boolean isEmpty() { return false; } @Override public boolean containsKey(Object key) { return get(key) != null; } @Override public boolean containsValue(Object value) { if (value == null) { return false; } for (Entry entry : entries) { if (entry.getValue().equals(value)) { return true; } } return false; } // TODO: Serialization of the map views should serialize the map, and // deserialization should call entrySet(), keySet(), or values() on the // deserialized map. The views are serializable since the Immutable* classes // are. private transient ImmutableSet> entrySet; @Override public ImmutableSet> entrySet() { ImmutableSet> es = entrySet; return (es == null) ? (entrySet = new EntrySet(this)) : es; } private static class EntrySet extends ImmutableSet.ArrayImmutableSet> { final RegularImmutableMap map; EntrySet(RegularImmutableMap map) { super(map.entries); this.map = map; } @Override public boolean contains(Object target) { if (target instanceof Entry) { Entry entry = (Entry) target; V mappedValue = map.get(entry.getKey()); return mappedValue != null && mappedValue.equals(entry.getValue()); } return false; } } private transient ImmutableSet keySet; @Override public ImmutableSet keySet() { ImmutableSet ks = keySet; return (ks == null) ? (keySet = new KeySet(this)) : ks; } private static class KeySet extends ImmutableSet.TransformedImmutableSet, K> { final RegularImmutableMap map; KeySet(RegularImmutableMap map) { super(map.entries, map.keySetHashCode); this.map = map; } @Override K transform(Entry element) { return element.getKey(); } @Override public boolean contains(Object target) { return map.containsKey(target); } } private transient ImmutableCollection values; @Override public ImmutableCollection values() { ImmutableCollection v = values; return (v == null) ? (values = new Values(this)) : v; } private static class Values extends ImmutableCollection { final RegularImmutableMap map; Values(RegularImmutableMap map) { this.map = map; } public int size() { return map.entries.length; } @Override public boolean isEmpty() { return false; } @Override public UnmodifiableIterator iterator() { Iterator iterator = new AbstractIterator() { int index = 0; @Override protected V computeNext() { return (index < map.entries.length) ? map.entries[index++].getValue() : endOfData(); } }; // Though the AbstractIterator is unmodifiable, it isn't an // UnmodifiableIterator. return Iterators.unmodifiableIterator(iterator); } @Override public boolean contains(Object target) { return map.containsValue(target); } } @Override public String toString() { StringBuilder result = new StringBuilder(size() * 16) .append('{') .append(entries[0]); for (int e = 1; e < entries.length; e++) { result.append(", ").append(entries[e].toString()); } return result.append('}').toString(); } } /* * Serialized type for all ImmutableMap instances. It captures the logical * contents and they are reconstructed using public factory methods. This * ensures that the implementation types remain as implementation details. */ private static class SerializedForm implements Serializable { final Object[] keys; final Object[] values; SerializedForm(ImmutableMap map) { keys = new Object[map.size()]; values = new Object[map.size()]; int i = 0; for (Entry entry : map.entrySet()) { keys[i] = entry.getKey(); values[i] = entry.getValue(); i++; } } Object readResolve() { Builder builder = new Builder(); for (int i = 0; i < keys.length; i++) { builder.put(keys[i], values[i]); } return builder.build(); } private static final long serialVersionUID = 0; } Object writeReplace() { return new SerializedForm(this); } } guice-3.0/core/src/com/google/inject/internal/util/Nullable.java0000644000175000017500000000237511461631440024572 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The presence of this annotation on a method parameter indicates that * {@code null} is an acceptable value for that parameter. It should not be * used for parameters of primitive types. * *

This annotation may be used with the Google Web Toolkit (GWT). * * @author Kevin Bourrillion */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.FIELD}) public @interface Nullable { } guice-3.0/core/src/com/google/inject/internal/util/ImmutableSet.java0000644000175000017500000004763011461631440025432 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; /** * A high-performance, immutable {@code Set} with reliable, user-specified * iteration order. Does not permit null elements. * *

Unlike {@link Collections#unmodifiableSet}, which is a view of a * separate collection that can still change, an instance of this class contains * its own private data and will never change. This class is convenient * for {@code public static final} sets ("constant sets") and also lets you * easily make a "defensive copy" of a set provided to your class by a caller. * *

Warning: Like most sets, an {@code ImmutableSet} will not function * correctly if an element is modified after being placed in the set. For this * reason, and to avoid general confusion, it is strongly recommended to place * only immutable objects into this collection. * *

This class has been observed to perform significantly better than {@link * HashSet} for objects with very fast {@link Object#hashCode} implementations * (as a well-behaved immutable object should). While this class's factory * methods create hash-based instances, the {@link ImmutableSortedSet} subclass * performs binary searches instead. * *

Note: Although this class is not final, it cannot be subclassed * outside its package as it has no public or protected constructors. Thus, * instances of this type are guaranteed to be immutable. * * @see ImmutableList * @see ImmutableMap * @author Kevin Bourrillion * @author Nick Kralevich */ @SuppressWarnings("serial") // we're overriding default serialization public abstract class ImmutableSet extends ImmutableCollection implements Set { private static final ImmutableSet EMPTY_IMMUTABLE_SET = new EmptyImmutableSet(); /** * Returns the empty immutable set. This set behaves and performs comparably * to {@link Collections#emptySet}, and is preferable mainly for consistency * and maintainability of your code. */ // Casting to any type is safe because the set will never hold any elements. @SuppressWarnings({"unchecked"}) public static ImmutableSet of() { return (ImmutableSet) EMPTY_IMMUTABLE_SET; } /** * Returns an immutable set containing a single element. This set behaves and * performs comparably to {@link Collections#singleton}, but will not accept * a null element. It is preferable mainly for consistency and * maintainability of your code. */ public static ImmutableSet of(E element) { return new SingletonImmutableSet(element, element.hashCode()); } /** * Returns an immutable set containing the given elements, in order. Repeated * occurrences of an element (according to {@link Object#equals}) after the * first are ignored (but too many of these may result in the set being * sized inappropriately). * * @throws NullPointerException if any of {@code elements} is null */ public static ImmutableSet of(E... elements) { switch (elements.length) { case 0: return of(); case 1: return of(elements[0]); default: return create(Arrays.asList(elements), elements.length); } } /** * Returns an immutable set containing the given elements, in order. Repeated * occurrences of an element (according to {@link Object#equals}) after the * first are ignored (but too many of these may result in the set being * sized inappropriately). This method iterates over {@code elements} at most * once. * *

Note that if {@code s} is a {@code Set}, then {@code * ImmutableSet.copyOf(s)} returns an {@code ImmutableSet} containing * each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns * a {@code ImmutableSet>} containing one element (the given set * itself). * *

Note: Despite what the method name suggests, if {@code elements} * is an {@code ImmutableSet} (but not an {@code ImmutableSortedSet}), no copy * will actually be performed, and the given set itself will be returned. * * @throws NullPointerException if any of {@code elements} is null */ public static ImmutableSet copyOf(Iterable elements) { if (elements instanceof ImmutableSet) { @SuppressWarnings("unchecked") // all supported methods are covariant ImmutableSet set = (ImmutableSet) elements; return set; } return copyOfInternal(Collections2.toCollection(elements)); } /** * Returns an immutable set containing the given elements, in order. Repeated * occurrences of an element (according to {@link Object#equals}) after the * first are ignored. * * @throws NullPointerException if any of {@code elements} is null */ public static ImmutableSet copyOf(Iterator elements) { Collection list = Lists.newArrayList(elements); return copyOfInternal(list); } private static ImmutableSet copyOfInternal( Collection collection) { // TODO: Support concurrent collections that change while this method is // running. switch (collection.size()) { case 0: return of(); case 1: // TODO: Remove "ImmutableSet." when eclipse bug is fixed. return ImmutableSet.of(collection.iterator().next()); default: return create(collection, collection.size()); } } ImmutableSet() {} /** Returns {@code true} if the {@code hashCode()} method runs quickly. */ boolean isHashCodeFast() { return false; } @Override public boolean equals(@Nullable Object object) { if (object == this) { return true; } if (object instanceof ImmutableSet && isHashCodeFast() && ((ImmutableSet) object).isHashCodeFast() && hashCode() != object.hashCode()) { return false; } return Collections2.setEquals(this, object); } @Override public int hashCode() { int hashCode = 0; for (Object o : this) { hashCode += o.hashCode(); } return hashCode; } // This declaration is needed to make Set.iterator() and // ImmutableCollection.iterator() consistent. @Override public abstract UnmodifiableIterator iterator(); @Override public String toString() { if (isEmpty()) { return "[]"; } Iterator iterator = iterator(); StringBuilder result = new StringBuilder(size() * 16); result.append('[').append(iterator.next().toString()); for (int i = 1; i < size(); i++) { result.append(", ").append(iterator.next().toString()); } return result.append(']').toString(); } private static final class EmptyImmutableSet extends ImmutableSet { public int size() { return 0; } @Override public boolean isEmpty() { return true; } @Override public boolean contains(Object target) { return false; } @Override public UnmodifiableIterator iterator() { return Iterators.emptyIterator(); } private static final Object[] EMPTY_ARRAY = new Object[0]; @Override public Object[] toArray() { return EMPTY_ARRAY; } @Override public T[] toArray(T[] a) { if (a.length > 0) { a[0] = null; } return a; } @Override public boolean containsAll(Collection targets) { return targets.isEmpty(); } @Override public boolean equals(@Nullable Object object) { if (object instanceof Set) { Set that = (Set) object; return that.isEmpty(); } return false; } @Override public final int hashCode() { return 0; } @Override boolean isHashCodeFast() { return true; } @Override public String toString() { return "[]"; } } private static final class SingletonImmutableSet extends ImmutableSet { final E element; final int hashCode; SingletonImmutableSet(E element, int hashCode) { this.element = element; this.hashCode = hashCode; } public int size() { return 1; } @Override public boolean isEmpty() { return false; } @Override public boolean contains(Object target) { return element.equals(target); } @Override public UnmodifiableIterator iterator() { return Iterators.singletonIterator(element); } @Override public Object[] toArray() { return new Object[] { element }; } @SuppressWarnings({"unchecked"}) @Override public T[] toArray(T[] array) { if (array.length == 0) { array = ObjectArrays.newArray(array, 1); } else if (array.length > 1) { array[1] = null; } array[0] = (T) element; return array; } @Override public boolean equals(@Nullable Object object) { if (object == this) { return true; } if (object instanceof Set) { Set that = (Set) object; return that.size() == 1 && element.equals(that.iterator().next()); } return false; } @Override public final int hashCode() { return hashCode; } @Override boolean isHashCodeFast() { return true; } @Override public String toString() { String elementToString = element.toString(); return new StringBuilder(elementToString.length() + 2) .append('[') .append(elementToString) .append(']') .toString(); } } private static ImmutableSet create( Iterable iterable, int count) { // count is always the (nonzero) number of elements in the iterable int tableSize = Hashing.chooseTableSize(count); Object[] table = new Object[tableSize]; int mask = tableSize - 1; List elements = new ArrayList(count); int hashCode = 0; for (E element : iterable) { int hash = element.hashCode(); for (int i = Hashing.smear(hash); true; i++) { int index = i & mask; Object value = table[index]; if (value == null) { // Came to an empty bucket. Put the element here. table[index] = element; elements.add(element); hashCode += hash; break; } else if (value.equals(element)) { break; // Found a duplicate. Nothing to do. } } } // The iterable might have contained only duplicates of the same element. return (elements.size() == 1) ? new SingletonImmutableSet(elements.get(0), hashCode) : new RegularImmutableSet(elements.toArray(), hashCode, table, mask); } abstract static class ArrayImmutableSet extends ImmutableSet { final Object[] elements; // the elements (two or more) in the desired order ArrayImmutableSet(Object[] elements) { this.elements = elements; } public int size() { return elements.length; } @Override public boolean isEmpty() { return false; } /* * The cast is safe because the only way to create an instance is via the * create() method above, which only permits elements of type E. */ @SuppressWarnings("unchecked") @Override public UnmodifiableIterator iterator() { return (UnmodifiableIterator) Iterators.forArray(elements); } @Override public Object[] toArray() { Object[] array = new Object[size()]; System.arraycopy(elements, 0, array, 0, size()); return array; } @Override public T[] toArray(T[] array) { int size = size(); if (array.length < size) { array = ObjectArrays.newArray(array, size); } else if (array.length > size) { array[size] = null; } System.arraycopy(elements, 0, array, 0, size); return array; } @Override public boolean containsAll(Collection targets) { if (targets == this) { return true; } if (!(targets instanceof ArrayImmutableSet)) { return super.containsAll(targets); } if (targets.size() > size()) { return false; } for (Object target : ((ArrayImmutableSet) targets).elements) { if (!contains(target)) { return false; } } return true; } } private static final class RegularImmutableSet extends ArrayImmutableSet { final Object[] table; // the same elements in hashed positions (plus nulls) final int mask; // 'and' with an int to get a valid table index final int hashCode; RegularImmutableSet(Object[] elements, int hashCode, Object[] table, int mask) { super(elements); this.table = table; this.mask = mask; this.hashCode = hashCode; } @Override public boolean contains(Object target) { if (target == null) { return false; } for (int i = Hashing.smear(target.hashCode()); true; i++) { Object candidate = table[i & mask]; if (candidate == null) { return false; } if (candidate.equals(target)) { return true; } } } @Override public int hashCode() { return hashCode; } @Override boolean isHashCodeFast() { return true; } } /** such as ImmutableMap.keySet() */ abstract static class TransformedImmutableSet extends ImmutableSet { final D[] source; final int hashCode; TransformedImmutableSet(D[] source, int hashCode) { this.source = source; this.hashCode = hashCode; } abstract E transform(D element); public int size() { return source.length; } @Override public boolean isEmpty() { return false; } @Override public UnmodifiableIterator iterator() { Iterator iterator = new AbstractIterator() { int index = 0; @Override protected E computeNext() { return index < source.length ? transform(source[index++]) : endOfData(); } }; // Though the AbstractIterator is unmodifiable, it isn't an // UnmodifiableIterator. return Iterators.unmodifiableIterator(iterator); } @Override public Object[] toArray() { return toArray(new Object[size()]); } @SuppressWarnings("unchecked") @Override public T[] toArray(T[] array) { int size = size(); if (array.length < size) { array = ObjectArrays.newArray(array, size); } else if (array.length > size) { array[size] = null; } for (int i = 0; i < source.length; i++) { array[i] = (T) transform(source[i]); } return array; } @Override public final int hashCode() { return hashCode; } @Override boolean isHashCodeFast() { return true; } } /* * This class is used to serialize all ImmutableSet instances, regardless of * implementation type. It captures their "logical contents" and they are * reconstructed using public static factories. This is necessary to ensure * that the existence of a particular implementation type is an implementation * detail. */ private static class SerializedForm implements Serializable { final Object[] elements; SerializedForm(Object[] elements) { this.elements = elements; } Object readResolve() { return of(elements); } private static final long serialVersionUID = 0; } @Override Object writeReplace() { return new SerializedForm(toArray()); } /** * Returns a new builder. The generated builder is equivalent to the builder * created by the {@link Builder} constructor. */ public static Builder builder() { return new Builder(); } /** * A builder for creating immutable set instances, especially * {@code public static final} sets ("constant sets"). * *

Example: *

{@code
   *   public static final ImmutableSet GOOGLE_COLORS
   *       = new ImmutableSet.Builder()
   *           .addAll(WEBSAFE_COLORS)
   *           .add(new Color(0, 191, 255))
   *           .build();}
* *

Builder instances can be reused - it is safe to call {@link #build} * multiple times to build multiple sets in series. Each set * is a superset of the set created before it. */ public static class Builder { final ArrayList contents = Lists.newArrayList(); /** * Creates a new builder. The returned builder is equivalent to the builder * generated by {@link ImmutableSet#builder}. */ public Builder() {} /** * Adds {@code element} to the {@code ImmutableSet}. If the * {@code ImmutableSet} already contains {@code element}, then * {@code add} has no effect. (only the previously added element * is retained). * * @param element the element to add * @return this {@code Builder} object * @throws NullPointerException if {@code element} is null */ public Builder add(E element) { Preconditions.checkNotNull(element, "element cannot be null"); contents.add(element); return this; } /** * Adds each element of {@code elements} to the {@code ImmutableSet}, * ignoring duplicate elements (only the first duplicate element is added). * * @param elements the elements to add * @return this {@code Builder} object * @throws NullPointerException if {@code elements} is or contains null */ public Builder add(E... elements) { Preconditions.checkNotNull(elements, "elements cannot be null"); List elemsAsList = Arrays.asList(elements); Preconditions.checkContentsNotNull(elemsAsList, "elements cannot contain null"); contents.addAll(elemsAsList); return this; } /** * Adds each element of {@code elements} to the {@code ImmutableSet}, * ignoring duplicate elements (only the first duplicate element is added). * * @param elements the {@code Iterable} to add to the {@code ImmutableSet} * @return this {@code Builder} object * @throws NullPointerException if {@code elements} is or contains null */ public Builder addAll(Iterable elements) { if (elements instanceof Collection) { @SuppressWarnings("unchecked") Collection collection = (Collection) elements; contents.ensureCapacity(contents.size() + collection.size()); } for (E elem : elements) { Preconditions.checkNotNull(elem, "elements contains a null"); contents.add(elem); } return this; } /** * Adds each element of {@code elements} to the {@code ImmutableSet}, * ignoring duplicate elements (only the first duplicate element is added). * * @param elements the elements to add to the {@code ImmutableSet} * @return this {@code Builder} object * @throws NullPointerException if {@code elements} is or contains null */ public Builder addAll(Iterator elements) { while (elements.hasNext()) { E element = elements.next(); Preconditions.checkNotNull(element, "element cannot be null"); contents.add(element); } return this; } /** * Returns a newly-created {@code ImmutableSet} based on the contents of * the {@code Builder}. */ public ImmutableSet build() { return copyOf(contents); } } } guice-3.0/core/src/com/google/inject/internal/util/CustomConcurrentHashMap.java0000644000175000017500000021451511461631440027614 0ustar drazzibdrazzib/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.util.AbstractCollection; import java.util.AbstractMap; import java.util.AbstractSet; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.locks.ReentrantLock; /** * A framework for concurrent hash map implementations. The * CustomConcurrentHashMap class itself is not extensible and does not contain * any methods. Use {@link Builder} to create a custom concurrent hash map * instance. Client libraries implement {@link Strategy}, and this class * provides the surrounding concurrent data structure which implements {@link * ConcurrentMap}. Additionally supports implementing maps where {@link * Map#get} atomically computes values on demand (see {@link * Builder#buildComputingMap(ComputingStrategy, com.google.inject.internal.util.Function)}). * *

The resulting hash table supports full concurrency of retrievals and * adjustable expected concurrency for updates. Even though all operations are * thread-safe, retrieval operations do not entail locking, * and there is not any support for locking the entire table * in a way that prevents all access. * *

Retrieval operations (including {@link Map#get}) generally do not * block, so may overlap with update operations (including * {@link Map#put} and {@link Map#remove}). Retrievals reflect the results * of the most recently completed update operations holding * upon their onset. For aggregate operations such as {@link Map#putAll} * and {@link Map#clear}, concurrent retrievals may reflect insertion or * removal of only some entries. Similarly, iterators return elements * reflecting the state of the hash table at some point at or since the * creation of the iterator. They do not throw * {@link java.util.ConcurrentModificationException}. However, iterators can * only be used by one thread at a time. * *

The resulting {@link ConcurrentMap} and its views and iterators implement * all of the optional methods of the {@link java.util.Map} and {@link * java.util.Iterator} interfaces. Partially reclaimed entries are never * exposed through the views or iterators. * *

For example, the following strategy emulates the behavior of * {@link java.util.concurrent.ConcurrentHashMap}: * *

 {@code
 * class ConcurrentHashMapStrategy
 *     implements CustomConcurrentHashMap.Strategy>, Serializable {
 *   public InternalEntry newEntry(K key, int hash,
 *       InternalEntry next) {
 *     return new InternalEntry(key, hash, null, next);
 *   }
 *   public InternalEntry copyEntry(K key,
 *       InternalEntry original, InternalEntry next) {
 *     return new InternalEntry(key, original.hash, original.value, next);
 *   }
 *   public void setValue(InternalEntry entry, V value) {
 *     entry.value = value;
 *   }
 *   public V getValue(InternalEntry entry) { return entry.value; }
 *   public boolean equalKeys(K a, Object b) { return a.equals(b); }
 *   public boolean equalValues(V a, Object b) { return a.equals(b); }
 *   public int hashKey(Object key) { return key.hashCode(); }
 *   public K getKey(InternalEntry entry) { return entry.key; }
 *   public InternalEntry getNext(InternalEntry entry) {
 *     return entry.next;
 *   }
 *   public int getHash(InternalEntry entry) { return entry.hash; }
 *   public void setInternals(CustomConcurrentHashMap.Internals> internals) {} // ignored
 * }
 *
 * class InternalEntry {
 *   final K key;
 *   final int hash;
 *   volatile V value;
 *   final InternalEntry next;
 *   InternalEntry(K key, int hash, V value, InternalEntry next) {
 *     this.key = key;
 *     this.hash = hash;
 *     this.value = value;
 *     this.next = next;
 *   }
 * }
 * }
* * To create a {@link java.util.concurrent.ConcurrentMap} using the strategy * above: * *
{@code
 *   ConcurrentMap map = new CustomConcurrentHashMap.Builder()
 *       .build(new ConcurrentHashMapStrategy());
 * }
* * @author Bob Lee * @author Doug Lea */ final class CustomConcurrentHashMap { /** Prevents instantiation. */ private CustomConcurrentHashMap() {} /** * Builds a custom concurrent hash map. */ final static class Builder { float loadFactor = 0.75f; int initialCapacity = 16; int concurrencyLevel = 16; /** * Sets a custom load factor (defaults to 0.75). * * @throws IllegalArgumentException if loadFactor <= 0 */ public Builder loadFactor(float loadFactor) { if (loadFactor <= 0) { throw new IllegalArgumentException(); } this.loadFactor = loadFactor; return this; } /** * Sets a custom initial capacity (defaults to 16). Resizing this or any * other kind of hash table is a relatively slow operation, so, when * possible, it is a good idea to provide estimates of expected table * sizes. * * @throws IllegalArgumentException if initialCapacity < 0 */ public Builder initialCapacity(int initialCapacity) { if (initialCapacity < 0) { throw new IllegalArgumentException(); } this.initialCapacity = initialCapacity; return this; } /** * Guides the allowed concurrency among update operations. Used as a * hint for internal sizing. The table is internally partitioned to try to * permit the indicated number of concurrent updates without contention. * Because placement in hash tables is essentially random, the actual * concurrency will vary. Ideally, you should choose a value to accommodate * as many threads as will ever concurrently modify the table. Using a * significantly higher value than you need can waste space and time, * and a significantly lower value can lead to thread contention. But * overestimates and underestimates within an order of magnitude do * not usually have much noticeable impact. A value of one is * appropriate when it is known that only one thread will modify and * all others will only read. Defaults to {@literal 16}. * * @throws IllegalArgumentException if concurrencyLevel < 0 */ public Builder concurrencyLevel(int concurrencyLevel) { if (concurrencyLevel <= 0) { throw new IllegalArgumentException(); } this.concurrencyLevel = concurrencyLevel; return this; } /** * Creates a new concurrent hash map backed by the given strategy. * * @param strategy used to implement and manipulate the entries * * @param the type of keys to be stored in the returned map * @param the type of values to be stored in the returned map * @param the type of internal entry to be stored in the returned map * * @throws NullPointerException if strategy is null */ public ConcurrentMap buildMap(Strategy strategy) { if (strategy == null) { throw new NullPointerException("strategy"); } return new Impl(strategy, this); } /** * Creates a {@link ConcurrentMap}, backed by the given strategy, that * supports atomic, on-demand computation of values. {@link Map#get} * returns the value corresponding to the given key, atomically computes * it using the computer function passed to this builder, or waits for * another thread to compute the value if necessary. Only one value will * be computed for each key at a given time. * *

If an entry's value has not finished computing yet, query methods * besides {@link java.util.Map#get} return immediately as if an entry * doesn't exist. In other words, an entry isn't externally visible until * the value's computation completes. * *

{@link Map#get} in the returned map implementation throws: *

    *
  • {@link NullPointerException} if the key is null or the * computer returns null
  • *
  • or {@link ComputationException} wrapping an exception thrown by the * computation
  • *
* *

Note: Callers of {@code get()} must ensure that the key * argument is of type {@code K}. {@code Map.get()} takes {@code Object}, * so the key type is not checked at compile time. Passing an object of * a type other than {@code K} can result in that object being unsafely * passed to the computer function as type {@code K} not to mention the * unsafe key being stored in the map. * * @param strategy used to implement and manipulate the entries * @param computer used to compute values for keys * * @param the type of keys to be stored in the returned map * @param the type of values to be stored in the returned map * @param the type of internal entry to be stored in the returned map * * @throws NullPointerException if strategy or computer is null */ public ConcurrentMap buildComputingMap( ComputingStrategy strategy, Function computer) { if (strategy == null) { throw new NullPointerException("strategy"); } if (computer == null) { throw new NullPointerException("computer"); } return new ComputingImpl(strategy, this, computer); } } /** * Implements behavior specific to the client's concurrent hash map * implementation. Used by the framework to create new entries and perform * operations on them. * *

Method parameters are never null unless otherwise specified. * *

Partially Reclaimed Entries

* *

This class does not allow {@code null} to be used as a key. * Setting values to null is not permitted, but entries may have null keys * or values for various reasons. For example, the key or value may have * been garbage collected or reclaimed through other means. * CustomConcurrentHashMap treats entries with null keys and values as * "partially reclaimed" and ignores them for the most part. Entries may * enter a partially reclaimed state but they must not leave it. Partially * reclaimed entries will not be copied over during table expansions, for * example. Strategy implementations should proactively remove partially * reclaimed entries so that {@link Map#isEmpty} and {@link Map#size()} * return up-to-date results. * * @param the type of keys to be stored in the returned map * @param the type of values to be stored in the returned map * @param internal entry type, not directly exposed to clients in map * views */ public interface Strategy { /** * Constructs a new entry for the given key with a pointer to the given * next entry. * *

This method may return different entry implementations * depending upon whether next is null or not. For example, if next is * null (as will often be the case), this factory might use an entry * class that doesn't waste memory on an unnecessary field. * * @param key for this entry * @param hash of key returned by {@link #hashKey} * @param next entry (used when implementing a hash bucket as a linked * list, for example), possibly null * @return a new entry */ abstract E newEntry(K key, int hash, E next); /** * Creates a copy of the given entry pointing to the given next entry. * Copies the value and any other implementation-specific state from * {@code original} to the returned entry. For example, * CustomConcurrentHashMap might use this method when removing other * entries or expanding the internal table. * * @param key for {@code original} as well as the returned entry. * Explicitly provided here to prevent reclamation of the key at an * inopportune time in implementations that don't otherwise keep * a strong reference to the key. * @param original entry from which the value and other * implementation-specific state should be copied * @param newNext the next entry the new entry should point to, possibly * null */ E copyEntry(K key, E original, E newNext); /** * Sets the value of an entry using volatile semantics. Values are set * synchronously on a per-entry basis. * * @param entry to set the value on * @param value to set */ void setValue(E entry, V value); /** * Gets the value of an entry using volatile semantics. * * @param entry to get the value from */ V getValue(E entry); /** * Returns true if the two given keys are equal, false otherwise. Neither * key will be null. * * @param a key from inside the map * @param b key passed from caller, not necesarily of type K * * @see Object#equals the same contractual obligations apply here */ boolean equalKeys(K a, Object b); /** * Returns true if the two given values are equal, false otherwise. Neither * value will be null. * * @param a value from inside the map * @param b value passed from caller, not necesarily of type V * * @see Object#equals the same contractual obligations apply here */ boolean equalValues(V a, Object b); /** * Returns a hash code for the given key. * * @see Object#hashCode the same contractual obligations apply here */ int hashKey(Object key); /** * Gets the key for the given entry. This may return null (for example, * if the key was reclaimed by the garbage collector). * * @param entry to get key from * @return key from the given entry */ K getKey(E entry); /** * Gets the next entry relative to the given entry, the exact same entry * that was provided to {@link Strategy#newEntry} when the given entry was * created. * * @return the next entry or null if null was passed to * {@link Strategy#newEntry} */ E getNext(E entry); /** * Returns the hash code that was passed to {@link Strategy#newEntry}) * when the given entry was created. */ int getHash(E entry); // TODO: // /** // * Notifies the strategy that an entry has been removed from the map. // * // * @param entry that was recently removed // */ // void remove(E entry); /** * Provides an API for interacting directly with the map's internal * entries to this strategy. Invoked once when the map is created. * Strategies that don't need access to the map's internal entries * can simply ignore the argument. * * @param internals of the map, enables direct interaction with the * internal entries */ void setInternals(Internals internals); } /** * Provides access to a map's internal entries. */ public interface Internals { // TODO: // /** // * Returns a set view of the internal entries. // */ // Set entrySet(); /** * Returns the internal entry corresponding to the given key from the map. * * @param key to retrieve entry for * * @throws NullPointerException if key is null */ E getEntry(K key); /** * Removes the given entry from the map if the value of the entry in the * map matches the given value. * * @param entry to remove * @param value entry must have for the removal to succeed * * @throws NullPointerException if entry is null */ boolean removeEntry(E entry, @Nullable V value); /** * Removes the given entry from the map. * * @param entry to remove * * @throws NullPointerException if entry is null */ boolean removeEntry(E entry); } /** * Extends {@link Strategy} to add support for computing values on-demand. * Implementations should typically intialize the entry's value to a * placeholder value in {@link #newEntry(Object, int, Object)} so that * {@link #waitForValue(Object)} can tell the difference between a * pre-intialized value and an in-progress computation. {@link * #copyEntry(Object, Object, Object)} must detect and handle the case where * an entry is copied in the middle of a computation. Implementations can * throw {@link UnsupportedOperationException} in {@link #setValue(Object, * Object)} if they wish to prevent users from setting values directly. * * @see Builder#buildComputingMap(ComputingStrategy, Function) */ public interface ComputingStrategy extends Strategy { /** * Computes a value for the given key and stores it in the given entry. * Called as a result of {@link Map#get}. If this method throws an * exception, CustomConcurrentHashMap will remove the entry and retry * the computation on subsequent requests. * * @param entry that was created * @param computer passed to {@link Builder#buildMap} * * @throws ComputationException if the computation threw an exception * @throws NullPointerException if the computer returned null * * @return the computed value */ V compute(K key, E entry, Function computer); /** * Gets a value from an entry waiting for the value to be set by {@link * #compute} if necessary. Returns null if a value isn't available at * which point CustomConcurrentHashMap tries to compute a new value. * * @param entry to return value from * @return stored value or null if the value isn't available * * @throws InterruptedException if the thread was interrupted while * waiting */ V waitForValue(E entry) throws InterruptedException; } /** * Applies a supplemental hash function to a given hash code, which defends * against poor quality hash functions. This is critical when the * concurrent hash map uses power-of-two length hash tables, that otherwise * encounter collisions for hash codes that do not differ in lower or upper * bits. * * @param h hash code */ private static int rehash(int h) { // Spread bits to regularize both segment and index locations, // using variant of single-word Wang/Jenkins hash. h += (h << 15) ^ 0xffffcd7d; h ^= (h >>> 10); h += (h << 3); h ^= (h >>> 6); h += (h << 2) + (h << 14); return h ^ (h >>> 16); } /** The concurrent hash map implementation. */ static class Impl extends AbstractMap implements ConcurrentMap, Serializable { /* * The basic strategy is to subdivide the table among Segments, * each of which itself is a concurrently readable hash table. */ /* ---------------- Constants -------------- */ /** * The maximum capacity, used if a higher value is implicitly specified by * either of the constructors with arguments. MUST be a power of two <= * 1<<30 to ensure that entries are indexable using ints. */ static final int MAXIMUM_CAPACITY = 1 << 30; /** * The maximum number of segments to allow; used to bound constructor * arguments. */ static final int MAX_SEGMENTS = 1 << 16; // slightly conservative /** * Number of unsynchronized retries in size and containsValue methods before * resorting to locking. This is used to avoid unbounded retries if tables * undergo continuous modification which would make it impossible to obtain * an accurate result. */ static final int RETRIES_BEFORE_LOCK = 2; /* ---------------- Fields -------------- */ /** * The strategy used to implement this map. */ final Strategy strategy; /** * Mask value for indexing into segments. The upper bits of a key's hash * code are used to choose the segment. */ final int segmentMask; /** * Shift value for indexing within segments. Helps prevent entries that * end up in the same segment from also ending up in the same bucket. */ final int segmentShift; /** * The segments, each of which is a specialized hash table */ final Segment[] segments; /** * The load factor for the hash table. */ final float loadFactor; /** * Creates a new, empty map with the specified strategy, initial capacity, * load factor and concurrency level. */ Impl(Strategy strategy, Builder builder) { this.loadFactor = builder.loadFactor; int concurrencyLevel = builder.concurrencyLevel; int initialCapacity = builder.initialCapacity; if (concurrencyLevel > MAX_SEGMENTS) { concurrencyLevel = MAX_SEGMENTS; } // Find power-of-two sizes best matching arguments int segmentShift = 0; int segmentCount = 1; while (segmentCount < concurrencyLevel) { ++segmentShift; segmentCount <<= 1; } this.segmentShift = 32 - segmentShift; segmentMask = segmentCount - 1; this.segments = newSegmentArray(segmentCount); if (initialCapacity > MAXIMUM_CAPACITY) { initialCapacity = MAXIMUM_CAPACITY; } int segmentCapacity = initialCapacity / segmentCount; if (segmentCapacity * segmentCount < initialCapacity) { ++segmentCapacity; } int segmentSize = 1; while (segmentSize < segmentCapacity) { segmentSize <<= 1; } for (int i = 0; i < this.segments.length; ++i) { this.segments[i] = new Segment(segmentSize); } this.strategy = strategy; strategy.setInternals(new InternalsImpl()); } int hash(Object key) { int h = strategy.hashKey(key); return rehash(h); } class InternalsImpl implements Internals, Serializable { static final long serialVersionUID = 0; public E getEntry(K key) { if (key == null) { throw new NullPointerException("key"); } int hash = hash(key); return segmentFor(hash).getEntry(key, hash); } public boolean removeEntry(E entry, V value) { if (entry == null) { throw new NullPointerException("entry"); } int hash = strategy.getHash(entry); return segmentFor(hash).removeEntry(entry, hash, value); } public boolean removeEntry(E entry) { if (entry == null) { throw new NullPointerException("entry"); } int hash = strategy.getHash(entry); return segmentFor(hash).removeEntry(entry, hash); } } @SuppressWarnings("unchecked") Segment[] newSegmentArray(int ssize) { // Note: This is the only way I could figure out how to create // a segment array (the compile has a tough time with arrays of // inner classes of generic types apparently). Safe because we're // restricting what can go in the array and no one has an // unrestricted reference. return (Segment[]) Array.newInstance(Segment.class, ssize); } /* ---------------- Small Utilities -------------- */ /** * Returns the segment that should be used for key with given hash * * @param hash the hash code for the key * @return the segment */ Segment segmentFor(int hash) { return segments[(hash >>> segmentShift) & segmentMask]; } /* ---------------- Inner Classes -------------- */ /** * Segments are specialized versions of hash tables. This subclasses from * ReentrantLock opportunistically, just to simplify some locking and avoid * separate construction. */ @SuppressWarnings("serial") // This class is never serialized. final class Segment extends ReentrantLock { /* * Segments maintain a table of entry lists that are ALWAYS * kept in a consistent state, so can be read without locking. * Next fields of nodes are immutable (final). All list * additions are performed at the front of each bin. This * makes it easy to check changes, and also fast to traverse. * When nodes would otherwise be changed, new nodes are * created to replace them. This works well for hash tables * since the bin lists tend to be short. (The average length * is less than two for the default load factor threshold.) * * Read operations can thus proceed without locking, but rely * on selected uses of volatiles to ensure that completed * write operations performed by other threads are * noticed. For most purposes, the "count" field, tracking the * number of elements, serves as that volatile variable * ensuring visibility. This is convenient because this field * needs to be read in many read operations anyway: * * - All (unsynchronized) read operations must first read the * "count" field, and should not look at table entries if * it is 0. * * - All (synchronized) write operations should write to * the "count" field after structurally changing any bin. * The operations must not take any action that could even * momentarily cause a concurrent read operation to see * inconsistent data. This is made easier by the nature of * the read operations in Map. For example, no operation * can reveal that the table has grown but the threshold * has not yet been updated, so there are no atomicity * requirements for this with respect to reads. * * As a guide, all critical volatile reads and writes to the * count field are marked in code comments. */ /** * The number of elements in this segment's region. */ volatile int count; /** * Number of updates that alter the size of the table. This is used * during bulk-read methods to make sure they see a consistent snapshot: * If modCounts change during a traversal of segments computing size or * checking containsValue, then we might have an inconsistent view of * state so (usually) must retry. */ int modCount; /** * The table is expanded when its size exceeds this threshold. (The * value of this field is always {@code (int)(capacity * loadFactor)}.) */ int threshold; /** * The per-segment table. */ volatile AtomicReferenceArray table; Segment(int initialCapacity) { setTable(newEntryArray(initialCapacity)); } AtomicReferenceArray newEntryArray(int size) { return new AtomicReferenceArray(size); } /** * Sets table to new HashEntry array. Call only while holding lock or in * constructor. */ void setTable(AtomicReferenceArray newTable) { this.threshold = (int) (newTable.length() * loadFactor); this.table = newTable; } /** * Returns properly casted first entry of bin for given hash. */ E getFirst(int hash) { AtomicReferenceArray table = this.table; return table.get(hash & (table.length() - 1)); } /* Specialized implementations of map methods */ public E getEntry(Object key, int hash) { Strategy s = Impl.this.strategy; if (count != 0) { // read-volatile for (E e = getFirst(hash); e != null; e = s.getNext(e)) { if (s.getHash(e) != hash) { continue; } K entryKey = s.getKey(e); if (entryKey == null) { continue; } if (s.equalKeys(entryKey, key)) { return e; } } } return null; } V get(Object key, int hash) { E entry = getEntry(key, hash); if (entry == null) { return null; } return strategy.getValue(entry); } boolean containsKey(Object key, int hash) { Strategy s = Impl.this.strategy; if (count != 0) { // read-volatile for (E e = getFirst(hash); e != null; e = s.getNext(e)) { if (s.getHash(e) != hash) { continue; } K entryKey = s.getKey(e); if (entryKey == null) { continue; } if (s.equalKeys(entryKey, key)) { // Return true only if this entry has a value. return s.getValue(e) != null; } } } return false; } boolean containsValue(Object value) { Strategy s = Impl.this.strategy; if (count != 0) { // read-volatile AtomicReferenceArray table = this.table; int length = table.length(); for (int i = 0; i < length; i++) { for (E e = table.get(i); e != null; e = s.getNext(e)) { V entryValue = s.getValue(e); // If the value disappeared, this entry is partially collected, // and we should skip it. if (entryValue == null) { continue; } if (s.equalValues(entryValue, value)) { return true; } } } } return false; } boolean replace(K key, int hash, V oldValue, V newValue) { Strategy s = Impl.this.strategy; lock(); try { for (E e = getFirst(hash); e != null; e = s.getNext(e)) { K entryKey = s.getKey(e); if (s.getHash(e) == hash && entryKey != null && s.equalKeys(key, entryKey)) { // If the value disappeared, this entry is partially collected, // and we should pretend like it doesn't exist. V entryValue = s.getValue(e); if (entryValue == null) { return false; } if (s.equalValues(entryValue, oldValue)) { s.setValue(e, newValue); return true; } } } return false; } finally { unlock(); } } V replace(K key, int hash, V newValue) { Strategy s = Impl.this.strategy; lock(); try { for (E e = getFirst(hash); e != null; e = s.getNext(e)) { K entryKey = s.getKey(e); if (s.getHash(e) == hash && entryKey != null && s.equalKeys(key, entryKey)) { // If the value disappeared, this entry is partially collected, // and we should pretend like it doesn't exist. V entryValue = s.getValue(e); if (entryValue == null) { return null; } s.setValue(e, newValue); return entryValue; } } return null; } finally { unlock(); } } V put(K key, int hash, V value, boolean onlyIfAbsent) { Strategy s = Impl.this.strategy; lock(); try { int count = this.count; if (count++ > this.threshold) { // ensure capacity expand(); } AtomicReferenceArray table = this.table; int index = hash & (table.length() - 1); E first = table.get(index); // Look for an existing entry. for (E e = first; e != null; e = s.getNext(e)) { K entryKey = s.getKey(e); if (s.getHash(e) == hash && entryKey != null && s.equalKeys(key, entryKey)) { // We found an existing entry. // If the value disappeared, this entry is partially collected, // and we should pretend like it doesn't exist. V entryValue = s.getValue(e); if (onlyIfAbsent && entryValue != null) { return entryValue; } s.setValue(e, value); return entryValue; } } // Create a new entry. ++modCount; E newEntry = s.newEntry(key, hash, first); s.setValue(newEntry, value); table.set(index, newEntry); this.count = count; // write-volatile return null; } finally { unlock(); } } /** * Expands the table if possible. */ void expand() { AtomicReferenceArray oldTable = table; int oldCapacity = oldTable.length(); if (oldCapacity >= MAXIMUM_CAPACITY) { return; } /* * Reclassify nodes in each list to new Map. Because we are * using power-of-two expansion, the elements from each bin * must either stay at same index, or move with a power of two * offset. We eliminate unnecessary node creation by catching * cases where old nodes can be reused because their next * fields won't change. Statistically, at the default * threshold, only about one-sixth of them need cloning when * a table doubles. The nodes they replace will be garbage * collectable as soon as they are no longer referenced by any * reader thread that may be in the midst of traversing table * right now. */ Strategy s = Impl.this.strategy; AtomicReferenceArray newTable = newEntryArray(oldCapacity << 1); threshold = (int) (newTable.length() * loadFactor); int newMask = newTable.length() - 1; for (int oldIndex = 0; oldIndex < oldCapacity; oldIndex++) { // We need to guarantee that any existing reads of old Map can // proceed. So we cannot yet null out each bin. E head = oldTable.get(oldIndex); if (head != null) { E next = s.getNext(head); int headIndex = s.getHash(head) & newMask; // Single node on list if (next == null) { newTable.set(headIndex, head); } else { // Reuse the consecutive sequence of nodes with the same target // index from the end of the list. tail points to the first // entry in the reusable list. E tail = head; int tailIndex = headIndex; for (E last = next; last != null; last = s.getNext(last)) { int newIndex = s.getHash(last) & newMask; if (newIndex != tailIndex) { // The index changed. We'll need to copy the previous entry. tailIndex = newIndex; tail = last; } } newTable.set(tailIndex, tail); // Clone nodes leading up to the tail. for (E e = head; e != tail; e = s.getNext(e)) { K key = s.getKey(e); if (key != null) { int newIndex = s.getHash(e) & newMask; E newNext = newTable.get(newIndex); newTable.set(newIndex, s.copyEntry(key, e, newNext)); } else { // Key was reclaimed. Skip entry. } } } } } table = newTable; } V remove(Object key, int hash) { Strategy s = Impl.this.strategy; lock(); try { int count = this.count - 1; AtomicReferenceArray table = this.table; int index = hash & (table.length() - 1); E first = table.get(index); for (E e = first; e != null; e = s.getNext(e)) { K entryKey = s.getKey(e); if (s.getHash(e) == hash && entryKey != null && s.equalKeys(entryKey, key)) { V entryValue = strategy.getValue(e); // All entries following removed node can stay // in list, but all preceding ones need to be // cloned. ++modCount; E newFirst = s.getNext(e); for (E p = first; p != e; p = s.getNext(p)) { K pKey = s.getKey(p); if (pKey != null) { newFirst = s.copyEntry(pKey, p, newFirst); } else { // Key was reclaimed. Skip entry. } } table.set(index, newFirst); this.count = count; // write-volatile return entryValue; } } return null; } finally { unlock(); } } boolean remove(Object key, int hash, Object value) { Strategy s = Impl.this.strategy; lock(); try { int count = this.count - 1; AtomicReferenceArray table = this.table; int index = hash & (table.length() - 1); E first = table.get(index); for (E e = first; e != null; e = s.getNext(e)) { K entryKey = s.getKey(e); if (s.getHash(e) == hash && entryKey != null && s.equalKeys(entryKey, key)) { V entryValue = strategy.getValue(e); if (value == entryValue || (value != null && entryValue != null && s.equalValues(entryValue, value))) { // All entries following removed node can stay // in list, but all preceding ones need to be // cloned. ++modCount; E newFirst = s.getNext(e); for (E p = first; p != e; p = s.getNext(p)) { K pKey = s.getKey(p); if (pKey != null) { newFirst = s.copyEntry(pKey, p, newFirst); } else { // Key was reclaimed. Skip entry. } } table.set(index, newFirst); this.count = count; // write-volatile return true; } else { return false; } } } return false; } finally { unlock(); } } public boolean removeEntry(E entry, int hash, V value) { Strategy s = Impl.this.strategy; lock(); try { int count = this.count - 1; AtomicReferenceArray table = this.table; int index = hash & (table.length() - 1); E first = table.get(index); for (E e = first; e != null; e = s.getNext(e)) { if (s.getHash(e) == hash && entry.equals(e)) { V entryValue = s.getValue(e); if (entryValue == value || (value != null && s.equalValues(entryValue, value))) { // All entries following removed node can stay // in list, but all preceding ones need to be // cloned. ++modCount; E newFirst = s.getNext(e); for (E p = first; p != e; p = s.getNext(p)) { K pKey = s.getKey(p); if (pKey != null) { newFirst = s.copyEntry(pKey, p, newFirst); } else { // Key was reclaimed. Skip entry. } } table.set(index, newFirst); this.count = count; // write-volatile return true; } else { return false; } } } return false; } finally { unlock(); } } public boolean removeEntry(E entry, int hash) { Strategy s = Impl.this.strategy; lock(); try { int count = this.count - 1; AtomicReferenceArray table = this.table; int index = hash & (table.length() - 1); E first = table.get(index); for (E e = first; e != null; e = s.getNext(e)) { if (s.getHash(e) == hash && entry.equals(e)) { // All entries following removed node can stay // in list, but all preceding ones need to be // cloned. ++modCount; E newFirst = s.getNext(e); for (E p = first; p != e; p = s.getNext(p)) { K pKey = s.getKey(p); if (pKey != null) { newFirst = s.copyEntry(pKey, p, newFirst); } else { // Key was reclaimed. Skip entry. } } table.set(index, newFirst); this.count = count; // write-volatile return true; } } return false; } finally { unlock(); } } void clear() { if (count != 0) { lock(); try { AtomicReferenceArray table = this.table; for (int i = 0; i < table.length(); i++) { table.set(i, null); } ++modCount; count = 0; // write-volatile } finally { unlock(); } } } } /* ---------------- Public operations -------------- */ /** * Returns {@code true} if this map contains no key-value mappings. * * @return {@code true} if this map contains no key-value mappings */ @Override public boolean isEmpty() { final Segment[] segments = this.segments; /* * We keep track of per-segment modCounts to avoid ABA * problems in which an element in one segment was added and * in another removed during traversal, in which case the * table was never actually empty at any point. Note the * similar use of modCounts in the size() and containsValue() * methods, which are the only other methods also susceptible * to ABA problems. */ int[] mc = new int[segments.length]; int mcsum = 0; for (int i = 0; i < segments.length; ++i) { if (segments[i].count != 0) { return false; } else { mcsum += mc[i] = segments[i].modCount; } } // If mcsum happens to be zero, then we know we got a snapshot // before any modifications at all were made. This is // probably common enough to bother tracking. if (mcsum != 0) { for (int i = 0; i < segments.length; ++i) { if (segments[i].count != 0 || mc[i] != segments[i].modCount) { return false; } } } return true; } /** * Returns the number of key-value mappings in this map. If the map * contains more than {@code Integer.MAX_VALUE} elements, returns * {@code Integer.MAX_VALUE}. * * @return the number of key-value mappings in this map */ @Override public int size() { final Segment[] segments = this.segments; long sum = 0; long check = 0; int[] mc = new int[segments.length]; // Try a few times to get accurate count. On failure due to // continuous async changes in table, resort to locking. for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) { check = 0; sum = 0; int mcsum = 0; for (int i = 0; i < segments.length; ++i) { sum += segments[i].count; mcsum += mc[i] = segments[i].modCount; } if (mcsum != 0) { for (int i = 0; i < segments.length; ++i) { check += segments[i].count; if (mc[i] != segments[i].modCount) { check = -1; // force retry break; } } } if (check == sum) { break; } } if (check != sum) { // Resort to locking all segments sum = 0; for (Segment segment : segments) { segment.lock(); } for (Segment segment : segments) { sum += segment.count; } for (Segment segment : segments) { segment.unlock(); } } if (sum > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } else { return (int) sum; } } /** * Returns the value to which the specified key is mapped, or {@code null} * if this map contains no mapping for the key. * *

More formally, if this map contains a mapping from a key {@code k} to * a value {@code v} such that {@code key.equals(k)}, then this method * returns {@code v}; otherwise it returns {@code null}. (There can be at * most one such mapping.) * * @throws NullPointerException if the specified key is null */ @Override public V get(Object key) { if (key == null) { throw new NullPointerException("key"); } int hash = hash(key); return segmentFor(hash).get(key, hash); } /** * Tests if the specified object is a key in this table. * * @param key possible key * @return {@code true} if and only if the specified object is a key in * this table, as determined by the {@code equals} method; * {@code false} otherwise. * @throws NullPointerException if the specified key is null */ @Override public boolean containsKey(Object key) { if (key == null) { throw new NullPointerException("key"); } int hash = hash(key); return segmentFor(hash).containsKey(key, hash); } /** * Returns {@code true} if this map maps one or more keys to the specified * value. Note: This method requires a full internal traversal of the hash * table, and so is much slower than method {@code containsKey}. * * @param value value whose presence in this map is to be tested * @return {@code true} if this map maps one or more keys to the specified * value * @throws NullPointerException if the specified value is null */ @Override public boolean containsValue(Object value) { if (value == null) { throw new NullPointerException("value"); } // See explanation of modCount use above final Segment[] segments = this.segments; int[] mc = new int[segments.length]; // Try a few times without locking for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) { int mcsum = 0; for (int i = 0; i < segments.length; ++i) { @SuppressWarnings("UnusedDeclaration") int c = segments[i].count; mcsum += mc[i] = segments[i].modCount; if (segments[i].containsValue(value)) { return true; } } boolean cleanSweep = true; if (mcsum != 0) { for (int i = 0; i < segments.length; ++i) { @SuppressWarnings("UnusedDeclaration") int c = segments[i].count; if (mc[i] != segments[i].modCount) { cleanSweep = false; break; } } } if (cleanSweep) { return false; } } // Resort to locking all segments for (Segment segment : segments) { segment.lock(); } boolean found = false; try { for (Segment segment : segments) { if (segment.containsValue(value)) { found = true; break; } } } finally { for (Segment segment : segments) { segment.unlock(); } } return found; } /** * Maps the specified key to the specified value in this table. Neither the * key nor the value can be null. * *

The value can be retrieved by calling the {@code get} method with a * key that is equal to the original key. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return the previous value associated with {@code key}, or {@code null} * if there was no mapping for {@code key} * @throws NullPointerException if the specified key or value is null */ @Override public V put(K key, V value) { if (key == null) { throw new NullPointerException("key"); } if (value == null) { throw new NullPointerException("value"); } int hash = hash(key); return segmentFor(hash).put(key, hash, value, false); } /** * {@inheritDoc} * * @return the previous value associated with the specified key, or * {@code null} if there was no mapping for the key * @throws NullPointerException if the specified key or value is null */ public V putIfAbsent(K key, V value) { if (key == null) { throw new NullPointerException("key"); } if (value == null) { throw new NullPointerException("value"); } int hash = hash(key); return segmentFor(hash).put(key, hash, value, true); } /** * Copies all of the mappings from the specified map to this one. These * mappings replace any mappings that this map had for any of the keys * currently in the specified map. * * @param m mappings to be stored in this map */ @Override public void putAll(Map m) { for (Entry e : m.entrySet()) { put(e.getKey(), e.getValue()); } } /** * Removes the key (and its corresponding value) from this map. This method * does nothing if the key is not in the map. * * @param key the key that needs to be removed * @return the previous value associated with {@code key}, or {@code null} * if there was no mapping for {@code key} * @throws NullPointerException if the specified key is null */ @Override public V remove(Object key) { if (key == null) { throw new NullPointerException("key"); } int hash = hash(key); return segmentFor(hash).remove(key, hash); } /** * {@inheritDoc} * * @throws NullPointerException if the specified key is null */ public boolean remove(Object key, Object value) { if (key == null) { throw new NullPointerException("key"); } int hash = hash(key); return segmentFor(hash).remove(key, hash, value); } /** * {@inheritDoc} * * @throws NullPointerException if any of the arguments are null */ public boolean replace(K key, V oldValue, V newValue) { if (key == null) { throw new NullPointerException("key"); } if (oldValue == null) { throw new NullPointerException("oldValue"); } if (newValue == null) { throw new NullPointerException("newValue"); } int hash = hash(key); return segmentFor(hash).replace(key, hash, oldValue, newValue); } /** * {@inheritDoc} * * @return the previous value associated with the specified key, or * {@code null} if there was no mapping for the key * @throws NullPointerException if the specified key or value is null */ public V replace(K key, V value) { if (key == null) { throw new NullPointerException("key"); } if (value == null) { throw new NullPointerException("value"); } int hash = hash(key); return segmentFor(hash).replace(key, hash, value); } /** * Removes all of the mappings from this map. */ @Override public void clear() { for (Segment segment : segments) { segment.clear(); } } Set keySet; /** * Returns a {@link java.util.Set} view of the keys contained in this map. * The set is backed by the map, so changes to the map are reflected in the * set, and vice-versa. The set supports element removal, which removes the * corresponding mapping from this map, via the {@code Iterator.remove}, * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and * {@code clear} operations. It does not support the {@code add} or * {@code addAll} operations. * *

The view's {@code iterator} is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException}, and * guarantees to traverse elements as they existed upon construction of the * iterator, and may (but is not guaranteed to) reflect any modifications * subsequent to construction. */ @Override public Set keySet() { Set ks = keySet; return (ks != null) ? ks : (keySet = new KeySet()); } Collection values; /** * Returns a {@link java.util.Collection} view of the values contained in * this map. The collection is backed by the map, so changes to the map are * reflected in the collection, and vice-versa. The collection supports * element removal, which removes the corresponding mapping from this map, * via the {@code Iterator.remove}, {@code Collection.remove}, * {@code removeAll}, {@code retainAll}, and {@code clear} operations. It * does not support the {@code add} or {@code addAll} operations. * *

The view's {@code iterator} is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException}, and * guarantees to traverse elements as they existed upon construction of the * iterator, and may (but is not guaranteed to) reflect any modifications * subsequent to construction. */ @Override public Collection values() { Collection vs = values; return (vs != null) ? vs : (values = new Values()); } Set> entrySet; /** * Returns a {@link java.util.Set} view of the mappings contained in this * map. The set is backed by the map, so changes to the map are reflected in * the set, and vice-versa. The set supports element removal, which removes * the corresponding mapping from the map, via the {@code Iterator.remove}, * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and * {@code clear} operations. It does not support the {@code add} or * {@code addAll} operations. * *

The view's {@code iterator} is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException}, and * guarantees to traverse elements as they existed upon construction of the * iterator, and may (but is not guaranteed to) reflect any modifications * subsequent to construction. */ public Set> entrySet() { Set> es = entrySet; return (es != null) ? es : (entrySet = new EntrySet()); } /* ---------------- Iterator Support -------------- */ abstract class HashIterator { int nextSegmentIndex; int nextTableIndex; AtomicReferenceArray currentTable; E nextEntry; WriteThroughEntry nextExternal; WriteThroughEntry lastReturned; HashIterator() { nextSegmentIndex = segments.length - 1; nextTableIndex = -1; advance(); } public boolean hasMoreElements() { return hasNext(); } final void advance() { nextExternal = null; if (nextInChain()) { return; } if (nextInTable()) { return; } while (nextSegmentIndex >= 0) { Segment seg = segments[nextSegmentIndex--]; if (seg.count != 0) { currentTable = seg.table; nextTableIndex = currentTable.length() - 1; if (nextInTable()) { return; } } } } /** * Finds the next entry in the current chain. Returns true if an entry * was found. */ boolean nextInChain() { Strategy s = Impl.this.strategy; if (nextEntry != null) { for (nextEntry = s.getNext(nextEntry); nextEntry != null; nextEntry = s.getNext(nextEntry)) { if (advanceTo(nextEntry)) { return true; } } } return false; } /** * Finds the next entry in the current table. Returns true if an entry * was found. */ boolean nextInTable() { while (nextTableIndex >= 0) { if ((nextEntry = currentTable.get(nextTableIndex--)) != null) { if (advanceTo(nextEntry) || nextInChain()) { return true; } } } return false; } /** * Advances to the given entry. Returns true if the entry was valid, * false if it should be skipped. */ boolean advanceTo(E entry) { Strategy s = Impl.this.strategy; K key = s.getKey(entry); V value = s.getValue(entry); if (key != null && value != null) { nextExternal = new WriteThroughEntry(key, value); return true; } else { // Skip partially reclaimed entry. return false; } } public boolean hasNext() { return nextExternal != null; } WriteThroughEntry nextEntry() { if (nextExternal == null) { throw new NoSuchElementException(); } lastReturned = nextExternal; advance(); return lastReturned; } public void remove() { if (lastReturned == null) { throw new IllegalStateException(); } Impl.this.remove(lastReturned.getKey()); lastReturned = null; } } final class KeyIterator extends HashIterator implements Iterator { public K next() { return super.nextEntry().getKey(); } } final class ValueIterator extends HashIterator implements Iterator { public V next() { return super.nextEntry().getValue(); } } /** * Custom Entry class used by EntryIterator.next(), that relays setValue * changes to the underlying map. */ final class WriteThroughEntry extends AbstractMapEntry { final K key; V value; WriteThroughEntry(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } /** * Set our entry's value and write through to the map. The value to * return is somewhat arbitrary here. Since a WriteThroughEntry does not * necessarily track asynchronous changes, the most recent "previous" * value could be different from what we return (or could even have been * removed in which case the put will re-establish). We do not and * cannot guarantee more. */ @Override public V setValue(V value) { if (value == null) { throw new NullPointerException(); } V oldValue = Impl.this.put(getKey(), value); this.value = value; return oldValue; } } final class EntryIterator extends HashIterator implements Iterator> { public Entry next() { return nextEntry(); } } final class KeySet extends AbstractSet { public Iterator iterator() { return new KeyIterator(); } public int size() { return Impl.this.size(); } @Override public boolean isEmpty() { return Impl.this.isEmpty(); } @Override public boolean contains(Object o) { return Impl.this.containsKey(o); } @Override public boolean remove(Object o) { return Impl.this.remove(o) != null; } @Override public void clear() { Impl.this.clear(); } } final class Values extends AbstractCollection { public Iterator iterator() { return new ValueIterator(); } public int size() { return Impl.this.size(); } @Override public boolean isEmpty() { return Impl.this.isEmpty(); } @Override public boolean contains(Object o) { return Impl.this.containsValue(o); } @Override public void clear() { Impl.this.clear(); } } final class EntrySet extends AbstractSet> { public Iterator> iterator() { return new EntryIterator(); } @Override public boolean contains(Object o) { if (!(o instanceof Entry)) { return false; } Entry e = (Entry) o; Object key = e.getKey(); if (key == null) { return false; } V v = Impl.this.get(key); return v != null && strategy.equalValues(v, e.getValue()); } @Override public boolean remove(Object o) { if (!(o instanceof Entry)) { return false; } Entry e = (Entry) o; Object key = e.getKey(); return key != null && Impl.this.remove(key, e.getValue()); } public int size() { return Impl.this.size(); } @Override public boolean isEmpty() { return Impl.this.isEmpty(); } @Override public void clear() { Impl.this.clear(); } } /* ---------------- Serialization Support -------------- */ private static final long serialVersionUID = 0; private void writeObject(java.io.ObjectOutputStream out) throws IOException { out.writeInt(size()); out.writeFloat(loadFactor); out.writeInt(segments.length); // concurrencyLevel out.writeObject(strategy); for (Entry entry : entrySet()) { out.writeObject(entry.getKey()); out.writeObject(entry.getValue()); } out.writeObject(null); // terminate entries } /** * Fields used during deserialization. We use a nested class so we don't * load them until we need them. We need to use reflection to set final * fields outside of the constructor. */ static class Fields { static final Field loadFactor = findField("loadFactor"); static final Field segmentShift = findField("segmentShift"); static final Field segmentMask = findField("segmentMask"); static final Field segments = findField("segments"); static final Field strategy = findField("strategy"); static Field findField(String name) { try { Field f = Impl.class.getDeclaredField(name); f.setAccessible(true); return f; } catch (NoSuchFieldException e) { throw new AssertionError(e); } } } @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { try { int initialCapacity = in.readInt(); float loadFactor = in.readFloat(); int concurrencyLevel = in.readInt(); Strategy strategy = (Strategy) in.readObject(); Fields.loadFactor.set(this, loadFactor); if (concurrencyLevel > MAX_SEGMENTS) { concurrencyLevel = MAX_SEGMENTS; } // Find power-of-two sizes best matching arguments int segmentShift = 0; int segmentCount = 1; while (segmentCount < concurrencyLevel) { ++segmentShift; segmentCount <<= 1; } Fields.segmentShift.set(this, 32 - segmentShift); Fields.segmentMask.set(this, segmentCount - 1); Fields.segments.set(this, newSegmentArray(segmentCount)); if (initialCapacity > MAXIMUM_CAPACITY) { initialCapacity = MAXIMUM_CAPACITY; } int segmentCapacity = initialCapacity / segmentCount; if (segmentCapacity * segmentCount < initialCapacity) { ++segmentCapacity; } int segmentSize = 1; while (segmentSize < segmentCapacity) { segmentSize <<= 1; } for (int i = 0; i < this.segments.length; ++i) { this.segments[i] = new Segment(segmentSize); } Fields.strategy.set(this, strategy); while (true) { K key = (K) in.readObject(); if (key == null) { break; // terminator } V value = (V) in.readObject(); put(key, value); } } catch (IllegalAccessException e) { throw new AssertionError(e); } } } static class ComputingImpl extends Impl { static final long serialVersionUID = 0; final ComputingStrategy computingStrategy; final Function computer; /** * Creates a new, empty map with the specified strategy, initial capacity, * load factor and concurrency level. */ ComputingImpl(ComputingStrategy strategy, Builder builder, Function computer) { super(strategy, builder); this.computingStrategy = strategy; this.computer = computer; } @Override public V get(Object k) { /* * This cast isn't safe, but we can rely on the fact that K is almost * always passed to Map.get(), and tools like IDEs and Findbugs can * catch situations where this isn't the case. * * The alternative is to add an overloaded method, but the chances of * a user calling get() instead of the new API and the risks inherent * in adding a new API outweigh this little hole. */ @SuppressWarnings("unchecked") K key = (K) k; if (key == null) { throw new NullPointerException("key"); } int hash = hash(key); Segment segment = segmentFor(hash); outer: while (true) { E entry = segment.getEntry(key, hash); if (entry == null) { boolean created = false; segment.lock(); try { // Try again--an entry could have materialized in the interim. entry = segment.getEntry(key, hash); if (entry == null) { // Create a new entry. created = true; int count = segment.count; if (count++ > segment.threshold) { // ensure capacity segment.expand(); } AtomicReferenceArray table = segment.table; int index = hash & (table.length() - 1); E first = table.get(index); ++segment.modCount; entry = computingStrategy.newEntry(key, hash, first); table.set(index, entry); segment.count = count; // write-volatile } } finally { segment.unlock(); } if (created) { // This thread solely created the entry. boolean success = false; try { V value = computingStrategy.compute(key, entry, computer); if (value == null) { throw new NullPointerException( "compute() returned null unexpectedly"); } success = true; return value; } finally { if (!success) { segment.removeEntry(entry, hash); } } } } // The entry already exists. Wait for the computation. boolean interrupted = false; try { while (true) { try { V value = computingStrategy.waitForValue(entry); if (value == null) { // Purge entry and try again. segment.removeEntry(entry, hash); continue outer; } return value; } catch (InterruptedException e) { interrupted = true; } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } } } /** * A basic, no-frills implementation of {@code Strategy} using {@link * SimpleInternalEntry}. Intended to be subclassed to provide customized * behavior. For example, the following creates a map that uses byte arrays as * keys:

   {@code
   *
   *   return new CustomConcurrentHashMap.Builder().buildMap(
   *       new SimpleStrategy() {
   *         public int hashKey(Object key) {
   *           return Arrays.hashCode((byte[]) key);
   *         }
   *         public boolean equalKeys(byte[] a, Object b) {
   *           return Arrays.equals(a, (byte[]) b);
   *         }
   *       });}
* * With nothing overridden, it yields map behavior equivalent to that of * {@link ConcurrentHashMap}. */ static class SimpleStrategy implements Strategy> { public SimpleInternalEntry newEntry( K key, int hash, SimpleInternalEntry next) { return new SimpleInternalEntry(key, hash, null, next); } public SimpleInternalEntry copyEntry(K key, SimpleInternalEntry original, SimpleInternalEntry next) { return new SimpleInternalEntry( key, original.hash, original.value, next); } public void setValue(SimpleInternalEntry entry, V value) { entry.value = value; } public V getValue(SimpleInternalEntry entry) { return entry.value; } public boolean equalKeys(K a, Object b) { return a.equals(b); } public boolean equalValues(V a, Object b) { return a.equals(b); } public int hashKey(Object key) { return key.hashCode(); } public K getKey(SimpleInternalEntry entry) { return entry.key; } public SimpleInternalEntry getNext(SimpleInternalEntry entry) { return entry.next; } public int getHash(SimpleInternalEntry entry) { return entry.hash; } public void setInternals( Internals> internals) { // ignore? } } /** * A basic, no-frills entry class used by {@link SimpleInternalEntry}. */ static class SimpleInternalEntry { final K key; final int hash; final SimpleInternalEntry next; volatile V value; SimpleInternalEntry( K key, int hash, @Nullable V value, SimpleInternalEntry next) { this.key = key; this.hash = hash; this.value = value; this.next = next; } } } guice-3.0/core/src/com/google/inject/internal/util/UnmodifiableIterator.java0000644000175000017500000000204011460132776027140 0ustar drazzibdrazzib/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Iterator; /** * An iterator that does not support {@link #remove}. * * @author Jared Levy */ public abstract class UnmodifiableIterator implements Iterator { /** * Guaranteed to throw an exception and leave the underlying data unmodified. * * @throws UnsupportedOperationException always */ public final void remove() { throw new UnsupportedOperationException(); } } guice-3.0/core/src/com/google/inject/internal/util/Classes.java0000644000175000017500000000476511461640300024431 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; /** * Class utilities. */ public final class Classes { public static boolean isInnerClass(Class clazz) { return !Modifier.isStatic(clazz.getModifiers()) && clazz.getEnclosingClass() != null; } public static boolean isConcrete(Class clazz) { int modifiers = clazz.getModifiers(); return !clazz.isInterface() && !Modifier.isAbstract(modifiers); } /** * Formats a member as concise string, such as {@code java.util.ArrayList.size}, * {@code java.util.ArrayList()} or {@code java.util.List.remove()}. */ public static String toString(Member member) { Class memberType = Classes.memberType(member); if (memberType == Method.class) { return member.getDeclaringClass().getName() + "." + member.getName() + "()"; } else if (memberType == Field.class) { return member.getDeclaringClass().getName() + "." + member.getName(); } else if (memberType == Constructor.class) { return member.getDeclaringClass().getName() + ".()"; } else { throw new AssertionError(); } } /** * Returns {@code Field.class}, {@code Method.class} or {@code Constructor.class}. */ public static Class memberType(Member member) { checkNotNull(member, "member"); if (member instanceof Field) { return Field.class; } else if (member instanceof Method) { return Method.class; } else if (member instanceof Constructor) { return Constructor.class; } else { throw new IllegalArgumentException( "Unsupported implementation class for Member, " + member.getClass()); } } } guice-3.0/core/src/com/google/inject/internal/util/Lists.java0000644000175000017500000000774411461631440024137 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; /** * Static utility methods pertaining to {@link List} instances. Also see this * class's counterparts {@link Sets} and {@link Maps}. * * @author Kevin Bourrillion * @author Mike Bostock */ public final class Lists { private Lists() {} // ArrayList /** * Creates an empty {@code ArrayList} instance. * *

Note: if you need an immutable empty list, use {@link * Collections#emptyList} instead. * * @return a new, empty {@code ArrayList} */ public static ArrayList newArrayList() { return new ArrayList(); } /** * Creates an {@code ArrayList} instance containing the given elements. * *

Note: if you need an immutable List, use {@link ImmutableList} * instead. * *

Note: due to a bug in javac 1.5.0_06, we cannot support the * following: * *

{@code List list = Lists.newArrayList(sub1, sub2);} * *

where {@code sub1} and {@code sub2} are references to subtypes of {@code * Base}, not of {@code Base} itself. To get around this, you must use: * *

{@code List list = Lists.newArrayList(sub1, sub2);} * * @param elements the elements that the list should contain, in order * @return a new {@code ArrayList} containing those elements */ public static ArrayList newArrayList(E... elements) { // Avoid integer overflow when a large array is passed in int capacity = computeArrayListCapacity(elements.length); ArrayList list = new ArrayList(capacity); Collections.addAll(list, elements); return list; } static int computeArrayListCapacity(int arraySize) { Preconditions.checkArgument(arraySize >= 0); // TODO: Figure out the right behavior, and document it return (int) Math.min(5L + arraySize + (arraySize / 10), Integer.MAX_VALUE); } /** * Creates an {@code ArrayList} instance containing the given elements. * * @param elements the elements that the list should contain, in order * @return a new {@code ArrayList} containing those elements */ public static ArrayList newArrayList(Iterable elements) { // Let ArrayList's sizing logic work, if possible if (elements instanceof Collection) { @SuppressWarnings("unchecked") Collection collection = (Collection) elements; return new ArrayList(collection); } else { return newArrayList(elements.iterator()); } } /** * Creates an {@code ArrayList} instance containing the given elements. * * @param elements the elements that the list should contain, in order * @return a new {@code ArrayList} containing those elements */ public static ArrayList newArrayList(Iterator elements) { ArrayList list = newArrayList(); while (elements.hasNext()) { list.add(elements.next()); } return list; } /** * Returns an unmodifiable list containing the specified first element and * the additional elements. */ public static ArrayList newArrayList(@Nullable E first, E[] rest) { ArrayList result = new ArrayList(rest.length + 1); result.add(first); for (E element : rest) { result.add(element); } return result; } }guice-3.0/core/src/com/google/inject/internal/util/FinalizableReferenceQueue.java0000644000175000017500000002451211461502550030074 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.logging.Level; import java.util.logging.Logger; /** * A reference queue with an associated background thread that dequeues * references and invokes {@link FinalizableReference#finalizeReferent()} on * them. * *

Keep a strong reference to this object until all of the associated * referents have been finalized. If this object is garbage collected earlier, * the backing thread will not invoke {@code finalizeReferent()} on the * remaining references. * * @author Bob Lee */ public class FinalizableReferenceQueue { /* * The Finalizer thread keeps a phantom reference to this object. When the * client (ReferenceMap, for example) no longer has a strong reference to * this object, the garbage collector will reclaim it and enqueue the * phantom reference. The enqueued reference will trigger the Finalizer to * stop. * * If this library is loaded in the system class loader, * FinalizableReferenceQueue can load Finalizer directly with no problems. * * If this library is loaded in an application class loader, it's important * that Finalizer not have a strong reference back to the class loader. * Otherwise, you could have a graph like this: * * Finalizer Thread * runs instance of -> Finalizer.class * loaded by -> Application class loader * which loaded -> ReferenceMap.class * which has a static -> FinalizableReferenceQueue instance * * Even if no other references to classes from the application class loader * remain, the Finalizer thread keeps an indirect strong reference to the * queue in ReferenceMap, which keeps the Finalizer running, and as a result, * the application class loader can never be reclaimed. * * This means that dynamically loaded web applications and OSGi bundles can't * be unloaded. * * If the library is loaded in an application class loader, we try to break * the cycle by loading Finalizer in its own independent class loader: * * System class loader * -> Application class loader * -> ReferenceMap * -> FinalizableReferenceQueue * -> etc. * -> Decoupled class loader * -> Finalizer * * Now, Finalizer no longer keeps an indirect strong reference to the * static FinalizableReferenceQueue field in ReferenceMap. The application * class loader can be reclaimed at which point the Finalizer thread will * stop and its decoupled class loader can also be reclaimed. * * If any of this fails along the way, we fall back to loading Finalizer * directly in the application class loader. */ private static final Logger logger = Logger.getLogger(FinalizableReferenceQueue.class.getName()); private static final String FINALIZER_CLASS_NAME = "com.google.inject.internal.util.Finalizer"; /** Reference to Finalizer.startFinalizer(). */ private static final Method startFinalizer; static { Class finalizer = loadFinalizer( new SystemLoader(), new DecoupledLoader(), new DirectLoader()); startFinalizer = getStartFinalizer(finalizer); } /** * The actual reference queue that our background thread will poll. */ final ReferenceQueue queue; /** * Whether or not the background thread started successfully. */ final boolean threadStarted; /** * Constructs a new queue. */ @SuppressWarnings("unchecked") public FinalizableReferenceQueue() { // We could start the finalizer lazily, but I'd rather it blow up early. ReferenceQueue queue; boolean threadStarted = false; try { queue = (ReferenceQueue) startFinalizer.invoke(null, FinalizableReference.class, this); threadStarted = true; } catch (IllegalAccessException e) { // Finalizer.startFinalizer() is public. throw new AssertionError(e); } catch (Throwable t) { logger.log(Level.INFO, "Failed to start reference finalizer thread." + " Reference cleanup will only occur when new references are" + " created.", t); queue = new ReferenceQueue(); } this.queue = queue; this.threadStarted = threadStarted; } /** * Repeatedly dequeues references from the queue and invokes * {@link FinalizableReference#finalizeReferent()} on them until the queue * is empty. This method is a no-op if the background thread was created * successfully. */ void cleanUp() { if (threadStarted) { return; } Reference reference; while ((reference = queue.poll()) != null) { /* * This is for the benefit of phantom references. Weak and soft * references will have already been cleared by this point. */ reference.clear(); try { ((FinalizableReference) reference).finalizeReferent(); } catch (Throwable t) { logger.log(Level.SEVERE, "Error cleaning up after reference.", t); } } } /** * Iterates through the given loaders until it finds one that can load * Finalizer. * * @return Finalizer.class */ private static Class loadFinalizer(FinalizerLoader... loaders) { for (FinalizerLoader loader : loaders) { Class finalizer = loader.loadFinalizer(); if (finalizer != null) { return finalizer; } } throw new AssertionError(); } /** * Loads Finalizer.class. */ interface FinalizerLoader { /** * Returns Finalizer.class or null if this loader shouldn't or can't load * it. * * @throws SecurityException if we don't have the appropriate priveleges */ Class loadFinalizer(); } /** * Tries to load Finalizer from the system class loader. If Finalizer is * in the system class path, we needn't create a separate loader. */ static class SystemLoader implements FinalizerLoader { public Class loadFinalizer() { ClassLoader systemLoader; try { systemLoader = ClassLoader.getSystemClassLoader(); } catch (SecurityException e) { logger.info("Not allowed to access system class loader."); return null; } if (systemLoader != null) { try { return systemLoader.loadClass(FINALIZER_CLASS_NAME); } catch (ClassNotFoundException e) { // Ignore. Finalizer is simply in a child class loader. return null; } } else { return null; } } } /** * Try to load Finalizer in its own class loader. If Finalizer's thread * had a direct reference to our class loader (which could be that of * a dynamically loaded web application or OSGi bundle), it would prevent * our class loader from getting garbage collected. */ static class DecoupledLoader implements FinalizerLoader { private static final String LOADING_ERROR = "Could not load Finalizer in" + " its own class loader. Loading Finalizer in the current class loader" + " instead. As a result, you will not be able to garbage collect this" + " class loader. To support reclaiming this class loader, either" + " resolve the underlying issue, or move Google Collections to your" + " system class path."; public Class loadFinalizer() { try { /* * We use URLClassLoader because it's the only concrete class loader * implementation in the JDK. If we used our own ClassLoader subclass, * Finalizer would indirectly reference this class loader: * * Finalizer.class -> * CustomClassLoader -> * CustomClassLoader.class -> * This class loader * * System class loader will (and must) be the parent. */ ClassLoader finalizerLoader = newLoader(getBaseUrl()); return finalizerLoader.loadClass(FINALIZER_CLASS_NAME); } catch (Exception e) { logger.log(Level.WARNING, LOADING_ERROR, e); return null; } } /** * Gets URL for base of path containing Finalizer.class. */ URL getBaseUrl() throws IOException { // Find URL pointing to Finalizer.class file. String finalizerPath = FINALIZER_CLASS_NAME.replace('.', '/') + ".class"; URL finalizerUrl = getClass().getClassLoader().getResource(finalizerPath); if (finalizerUrl == null) { throw new FileNotFoundException(finalizerPath); } // Find URL pointing to base of class path. String urlString = finalizerUrl.toString(); if (!urlString.endsWith(finalizerPath)) { throw new IOException("Unsupported path style: " + urlString); } urlString = urlString.substring(0, urlString.length() - finalizerPath.length()); return new URL(urlString); } /** Creates a class loader with the given base URL as its classpath. */ URLClassLoader newLoader(URL base) { return new URLClassLoader(new URL[] { base }); } } /** * Loads Finalizer directly using the current class loader. We won't be * able to garbage collect this class loader, but at least the world * doesn't end. */ static class DirectLoader implements FinalizerLoader { public Class loadFinalizer() { try { return Class.forName(FINALIZER_CLASS_NAME); } catch (ClassNotFoundException e) { throw new AssertionError(e); } } } /** * Looks up Finalizer.startFinalizer(). */ static Method getStartFinalizer(Class finalizer) { try { return finalizer.getMethod("startFinalizer", Class.class, Object.class); } catch (NoSuchMethodException e) { throw new AssertionError(e); } } } guice-3.0/core/src/com/google/inject/internal/util/Iterators.java0000644000175000017500000002322711461631440025007 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; import java.util.ListIterator; import java.util.NoSuchElementException; /** * This class contains static utility methods that operate on or return objects * of type {@code Iterator}. Also see the parallel implementations in {@link * Iterables}. * * @author Kevin Bourrillion * @author Scott Bonneau */ public final class Iterators { private Iterators() {} static final Iterator EMPTY_ITERATOR = new UnmodifiableIterator() { public boolean hasNext() { return false; } public Object next() { throw new NoSuchElementException(); } }; /** Returns the empty {@code Iterator}. */ // Casting to any type is safe since there are no actual elements. @SuppressWarnings("unchecked") public static UnmodifiableIterator emptyIterator() { return (UnmodifiableIterator) EMPTY_ITERATOR; } private static final ListIterator EMPTY_LIST_ITERATOR = new ListIterator() { public boolean hasNext() { return false; } public boolean hasPrevious() { return false; } public int nextIndex() { return 0; } public int previousIndex() { return -1; } public Object next() { throw new NoSuchElementException(); } public Object previous() { throw new NoSuchElementException(); } public void set(Object o) { throw new UnsupportedOperationException(); } public void add(Object o) { throw new UnsupportedOperationException(); } public void remove() { throw new UnsupportedOperationException(); } }; /** Returns the empty {@code ListIterator}. */ // Casting to any type is safe since there are no actual elements. @SuppressWarnings("unchecked") public static ListIterator emptyListIterator() { return (ListIterator) EMPTY_LIST_ITERATOR; } /** Returns an unmodifiable view of {@code iterator}. */ public static UnmodifiableIterator unmodifiableIterator( final Iterator iterator) { Preconditions.checkNotNull(iterator); return new UnmodifiableIterator() { public boolean hasNext() { return iterator.hasNext(); } public T next() { return iterator.next(); } }; } /** * Returns a string representation of {@code iterator}, with the format * {@code [e1, e2, ..., en]}. The iterator will be left exhausted: its * {@code hasNext()} method will return {@code false}. */ public static String toString(Iterator iterator) { if (!iterator.hasNext()) { return "[]"; } StringBuilder builder = new StringBuilder(); builder.append('[').append(iterator.next()); while (iterator.hasNext()) { builder.append(", ").append(iterator.next()); } return builder.append(']').toString(); } /** * Returns the single element contained in {@code iterator}. * * @throws NoSuchElementException if the iterator is empty * @throws IllegalArgumentException if the iterator contains multiple * elements. The state of the iterator is unspecified. */ public static T getOnlyElement(Iterator iterator) { T first = iterator.next(); if (!iterator.hasNext()) { return first; } StringBuilder sb = new StringBuilder(); sb.append("expected one element but was: <" + first); for (int i = 0; i < 4 && iterator.hasNext(); i++) { sb.append(", " + iterator.next()); } if (iterator.hasNext()) { sb.append(", ..."); } sb.append(">"); throw new IllegalArgumentException(sb.toString()); } /** * Combines multiple iterators into a single iterator. The returned iterator * iterates across the elements of each iterator in {@code inputs}. The input * iterators are not polled until necessary. * *

The returned iterator supports {@code remove()} when the corresponding * input iterator supports it. The methods of the returned iterator may throw * {@code NullPointerException} if any of the input iterators are null. */ public static Iterator concat( final Iterator> inputs) { Preconditions.checkNotNull(inputs); return new Iterator() { Iterator current = emptyIterator(); Iterator removeFrom; public boolean hasNext() { while (!current.hasNext() && inputs.hasNext()) { current = inputs.next(); } return current.hasNext(); } public T next() { if (!hasNext()) { throw new NoSuchElementException(); } removeFrom = current; return current.next(); } public void remove() { Preconditions.checkState(removeFrom != null, "no calls to next() since last call to remove()"); removeFrom.remove(); removeFrom = null; } }; } /** * Returns an iterator that applies {@code function} to each element of {@code * fromIterator}. * *

The returned iterator supports {@code remove()} if the provided iterator * does. After a successful {@code remove()} call, {@code fromIterator} no * longer contains the corresponding element. */ public static Iterator transform(final Iterator fromIterator, final Function function) { Preconditions.checkNotNull(fromIterator); Preconditions.checkNotNull(function); return new Iterator() { public boolean hasNext() { return fromIterator.hasNext(); } public T next() { F from = fromIterator.next(); return function.apply(from); } public void remove() { fromIterator.remove(); } }; } // Methods only in Iterators, not in Iterables /** * Returns an iterator containing the elements of {@code array} in order. The * returned iterator is a view of the array; subsequent changes to the array * will be reflected in the iterator. * *

Note: It is often preferable to represent your data using a * collection type, for example using {@link Arrays#asList(Object[])}, making * this method unnecessary. */ public static UnmodifiableIterator forArray(final T... array) { // optimized. benchmarks at nearly 2x of the straightforward impl return new UnmodifiableIterator() { final int length = array.length; int i = 0; public boolean hasNext() { return i < length; } public T next() { try { // 'return array[i++];' almost works T t = array[i]; i++; return t; } catch (ArrayIndexOutOfBoundsException e) { throw new NoSuchElementException(); } } }; } /** * Returns an iterator containing the elements in the specified range of * {@code array} in order. The returned iterator is a view of the array; * subsequent changes to the array will be reflected in the iterator. * * @param array array to read elements out of * @param offset index of first array element to retrieve * @param length number of elements in iteration * * @throws IndexOutOfBoundsException if {@code offset} is negative, * {@code length} is negative, or {@code offset + length > array.length} */ public static UnmodifiableIterator forArray( final T[] array, final int offset, final int length) { Preconditions.checkArgument(length >= 0); final int end = offset + length; // Technically we should give a slightly more descriptive error on overflow Preconditions.checkPositionIndexes(offset, end, array.length); // If length == 0 is a common enough case, we could return emptyIterator(). return new UnmodifiableIterator() { int i = offset; public boolean hasNext() { return i < end; } public T next() { if (!hasNext()) { throw new NoSuchElementException(); } return array[i++]; } }; } /** * Returns an iterator containing only {@code value}. */ public static UnmodifiableIterator singletonIterator( @Nullable final T value) { return new UnmodifiableIterator() { boolean done; public boolean hasNext() { return !done; } public T next() { if (done) { throw new NoSuchElementException(); } done = true; return value; } }; } /** * Adapts an {@code Iterator} to the {@code Enumeration} interface. * * @see Collections#enumeration(Collection) */ public static Enumeration asEnumeration(final Iterator iterator) { Preconditions.checkNotNull(iterator); return new Enumeration() { public boolean hasMoreElements() { return iterator.hasNext(); } public T nextElement() { return iterator.next(); } }; } } guice-3.0/core/src/com/google/inject/internal/util/ImmutableEntry.java0000644000175000017500000000214111461631440025764 0ustar drazzibdrazzib/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.Serializable; /** * @see Maps#immutableEntry(Object,Object) */ class ImmutableEntry extends AbstractMapEntry implements Serializable { private final K key; private final V value; ImmutableEntry(@Nullable K key, @Nullable V value) { this.key = key; this.value = value; } @Override public K getKey() { return key; } @Override public V getValue() { return value; } private static final long serialVersionUID = 0; } guice-3.0/core/src/com/google/inject/internal/util/Preconditions.java0000644000175000017500000004471511461631440025660 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Collection; import java.util.NoSuchElementException; /** * Simple static methods to be called at the start of your own methods to verify * correct arguments and state. This allows constructs such as *

 *     if (count <= 0) {
 *       throw new IllegalArgumentException("must be positive: " + count);
 *     }
* * to be replaced with the more compact *
 *     checkArgument(count > 0, "must be positive: %s", count);
* * Note that the sense of the expression is inverted; with {@code Preconditions} * you declare what you expect to be true, just as you do with an * * {@code assert} or a JUnit {@code assertTrue()} call. * *

Take care not to confuse precondition checking with other similar types * of checks! Precondition exceptions -- including those provided here, but also * {@link IndexOutOfBoundsException}, {@link NoSuchElementException}, {@link * UnsupportedOperationException} and others -- are used to signal that the * calling method has made an error. This tells the caller that it should * not have invoked the method when it did, with the arguments it did, or * perhaps ever. Postcondition or other invariant failures should not * throw these types of exceptions. * *

Note: The methods of the {@code Preconditions} class are highly * unusual in one way: they are supposed to throw exceptions, and promise * in their specifications to do so even when given perfectly valid input. That * is, {@code null} is a valid parameter to the method {@link * #checkNotNull(Object)} -- and technically this parameter could be even marked * as {@link com.google.inject.internal.util.Nullable} -- yet the method will still throw an exception anyway, * because that's what its contract says to do. * *

This class may be used with the Google Web Toolkit (GWT). * * @author Kevin Bourrillion */ public final class Preconditions { private Preconditions() {} /** * Ensures the truth of an expression involving one or more parameters to the * calling method. * * @param expression a boolean expression * @throws IllegalArgumentException if {@code expression} is false */ public static void checkArgument(boolean expression) { if (!expression) { throw new IllegalArgumentException(); } } /** * Ensures the truth of an expression involving one or more parameters to the * calling method. * * @param expression a boolean expression * @param errorMessage the exception message to use if the check fails; will * be converted to a string using {@link String#valueOf(Object)} * @throws IllegalArgumentException if {@code expression} is false */ public static void checkArgument(boolean expression, Object errorMessage) { if (!expression) { throw new IllegalArgumentException(String.valueOf(errorMessage)); } } /** * Ensures the truth of an expression involving one or more parameters to the * calling method. * * @param expression a boolean expression * @param errorMessageTemplate a template for the exception message should the * check fail. The message is formed by replacing each {@code %s} * placeholder in the template with an argument. These are matched by * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. * Unmatched arguments will be appended to the formatted message in square * braces. Unmatched placeholders will be left as-is. * @param errorMessageArgs the arguments to be substituted into the message * template. Arguments are converted to strings using * {@link String#valueOf(Object)}. * @throws IllegalArgumentException if {@code expression} is false * @throws NullPointerException if the check fails and either {@code * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let * this happen) */ public static void checkArgument(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) { if (!expression) { throw new IllegalArgumentException( format(errorMessageTemplate, errorMessageArgs)); } } /** * Ensures the truth of an expression involving the state of the calling * instance, but not involving any parameters to the calling method. * * @param expression a boolean expression * @throws IllegalStateException if {@code expression} is false */ public static void checkState(boolean expression) { if (!expression) { throw new IllegalStateException(); } } /** * Ensures the truth of an expression involving the state of the calling * instance, but not involving any parameters to the calling method. * * @param expression a boolean expression * @param errorMessage the exception message to use if the check fails; will * be converted to a string using {@link String#valueOf(Object)} * @throws IllegalStateException if {@code expression} is false */ public static void checkState(boolean expression, Object errorMessage) { if (!expression) { throw new IllegalStateException(String.valueOf(errorMessage)); } } /** * Ensures the truth of an expression involving the state of the calling * instance, but not involving any parameters to the calling method. * * @param expression a boolean expression * @param errorMessageTemplate a template for the exception message should the * check fail. The message is formed by replacing each {@code %s} * placeholder in the template with an argument. These are matched by * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. * Unmatched arguments will be appended to the formatted message in square * braces. Unmatched placeholders will be left as-is. * @param errorMessageArgs the arguments to be substituted into the message * template. Arguments are converted to strings using * {@link String#valueOf(Object)}. * @throws IllegalStateException if {@code expression} is false * @throws NullPointerException if the check fails and either {@code * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let * this happen) */ public static void checkState(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) { if (!expression) { throw new IllegalStateException( format(errorMessageTemplate, errorMessageArgs)); } } /** * Ensures that an object reference passed as a parameter to the calling * method is not null. * * @param reference an object reference * @return the non-null reference that was validated * @throws NullPointerException if {@code reference} is null */ public static T checkNotNull(T reference) { if (reference == null) { throw new NullPointerException(); } return reference; } /** * Ensures that an object reference passed as a parameter to the calling * method is not null. * * @param reference an object reference * @param errorMessage the exception message to use if the check fails; will * be converted to a string using {@link String#valueOf(Object)} * @return the non-null reference that was validated * @throws NullPointerException if {@code reference} is null */ public static T checkNotNull(T reference, Object errorMessage) { if (reference == null) { throw new NullPointerException(String.valueOf(errorMessage)); } return reference; } /** * Ensures that an object reference passed as a parameter to the calling * method is not null. * * @param reference an object reference * @param errorMessageTemplate a template for the exception message should the * check fail. The message is formed by replacing each {@code %s} * placeholder in the template with an argument. These are matched by * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. * Unmatched arguments will be appended to the formatted message in square * braces. Unmatched placeholders will be left as-is. * @param errorMessageArgs the arguments to be substituted into the message * template. Arguments are converted to strings using * {@link String#valueOf(Object)}. * @return the non-null reference that was validated * @throws NullPointerException if {@code reference} is null */ public static T checkNotNull(T reference, String errorMessageTemplate, Object... errorMessageArgs) { if (reference == null) { // If either of these parameters is null, the right thing happens anyway throw new NullPointerException( format(errorMessageTemplate, errorMessageArgs)); } return reference; } /** * Ensures that an {@code Iterable} object passed as a parameter to the * calling method is not null and contains no null elements. * * @param iterable the iterable to check the contents of * @return the non-null {@code iterable} reference just validated * @throws NullPointerException if {@code iterable} is null or contains at * least one null element */ public static > T checkContentsNotNull(T iterable) { if (containsOrIsNull(iterable)) { throw new NullPointerException(); } return iterable; } /** * Ensures that an {@code Iterable} object passed as a parameter to the * calling method is not null and contains no null elements. * * @param iterable the iterable to check the contents of * @param errorMessage the exception message to use if the check fails; will * be converted to a string using {@link String#valueOf(Object)} * @return the non-null {@code iterable} reference just validated * @throws NullPointerException if {@code iterable} is null or contains at * least one null element */ public static > T checkContentsNotNull( T iterable, Object errorMessage) { if (containsOrIsNull(iterable)) { throw new NullPointerException(String.valueOf(errorMessage)); } return iterable; } /** * Ensures that an {@code Iterable} object passed as a parameter to the * calling method is not null and contains no null elements. * * @param iterable the iterable to check the contents of * @param errorMessageTemplate a template for the exception message should the * check fail. The message is formed by replacing each {@code %s} * placeholder in the template with an argument. These are matched by * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. * Unmatched arguments will be appended to the formatted message in square * braces. Unmatched placeholders will be left as-is. * @param errorMessageArgs the arguments to be substituted into the message * template. Arguments are converted to strings using * {@link String#valueOf(Object)}. * @return the non-null {@code iterable} reference just validated * @throws NullPointerException if {@code iterable} is null or contains at * least one null element */ public static > T checkContentsNotNull(T iterable, String errorMessageTemplate, Object... errorMessageArgs) { if (containsOrIsNull(iterable)) { throw new NullPointerException( format(errorMessageTemplate, errorMessageArgs)); } return iterable; } private static boolean containsOrIsNull(Iterable iterable) { if (iterable == null) { return true; } if (iterable instanceof Collection) { Collection collection = (Collection) iterable; try { return collection.contains(null); } catch (NullPointerException e) { // A NPE implies that the collection doesn't contain null. return false; } } else { for (Object element : iterable) { if (element == null) { return true; } } return false; } } /** * Ensures that {@code index} specifies a valid element in an array, * list or string of size {@code size}. An element index may range from zero, * inclusive, to {@code size}, exclusive. * * @param index a user-supplied index identifying an element of an array, list * or string * @param size the size of that array, list or string * @throws IndexOutOfBoundsException if {@code index} is negative or is not * less than {@code size} * @throws IllegalArgumentException if {@code size} is negative */ public static void checkElementIndex(int index, int size) { checkElementIndex(index, size, "index"); } /** * Ensures that {@code index} specifies a valid element in an array, * list or string of size {@code size}. An element index may range from zero, * inclusive, to {@code size}, exclusive. * * @param index a user-supplied index identifying an element of an array, list * or string * @param size the size of that array, list or string * @param desc the text to use to describe this index in an error message * @throws IndexOutOfBoundsException if {@code index} is negative or is not * less than {@code size} * @throws IllegalArgumentException if {@code size} is negative */ public static void checkElementIndex(int index, int size, String desc) { checkArgument(size >= 0, "negative size: %s", size); if (index < 0) { throw new IndexOutOfBoundsException( format("%s (%s) must not be negative", desc, index)); } if (index >= size) { throw new IndexOutOfBoundsException( format("%s (%s) must be less than size (%s)", desc, index, size)); } } /** * Ensures that {@code index} specifies a valid position in an array, * list or string of size {@code size}. A position index may range from zero * to {@code size}, inclusive. * * @param index a user-supplied index identifying a position in an array, list * or string * @param size the size of that array, list or string * @throws IndexOutOfBoundsException if {@code index} is negative or is * greater than {@code size} * @throws IllegalArgumentException if {@code size} is negative */ public static void checkPositionIndex(int index, int size) { checkPositionIndex(index, size, "index"); } /** * Ensures that {@code index} specifies a valid position in an array, * list or string of size {@code size}. A position index may range from zero * to {@code size}, inclusive. * * @param index a user-supplied index identifying a position in an array, list * or string * @param size the size of that array, list or string * @param desc the text to use to describe this index in an error message * @throws IndexOutOfBoundsException if {@code index} is negative or is * greater than {@code size} * @throws IllegalArgumentException if {@code size} is negative */ public static void checkPositionIndex(int index, int size, String desc) { checkArgument(size >= 0, "negative size: %s", size); if (index < 0) { throw new IndexOutOfBoundsException(format( "%s (%s) must not be negative", desc, index)); } if (index > size) { throw new IndexOutOfBoundsException(format( "%s (%s) must not be greater than size (%s)", desc, index, size)); } } /** * Ensures that {@code start} and {@code end} specify a valid positions * in an array, list or string of size {@code size}, and are in order. A * position index may range from zero to {@code size}, inclusive. * * @param start a user-supplied index identifying a starting position in an * array, list or string * @param end a user-supplied index identifying a ending position in an array, * list or string * @param size the size of that array, list or string * @throws IndexOutOfBoundsException if either index is negative or is * greater than {@code size}, or if {@code end} is less than {@code start} * @throws IllegalArgumentException if {@code size} is negative */ public static void checkPositionIndexes(int start, int end, int size) { checkPositionIndex(start, size, "start index"); checkPositionIndex(end, size, "end index"); if (end < start) { throw new IndexOutOfBoundsException(format( "end index (%s) must not be less than start index (%s)", end, start)); } } /** * Substitutes each {@code %s} in {@code template} with an argument. These * are matched by position - the first {@code %s} gets {@code args[0]}, etc. * If there are more arguments than placeholders, the unmatched arguments will * be appended to the end of the formatted message in square braces. * * @param template a non-null string containing 0 or more {@code %s} * placeholders. * @param args the arguments to be substituted into the message * template. Arguments are converted to strings using * {@link String#valueOf(Object)}. Arguments can be null. */ // VisibleForTesting static String format(String template, Object... args) { // start substituting the arguments into the '%s' placeholders StringBuilder builder = new StringBuilder( template.length() + 16 * args.length); int templateStart = 0; int i = 0; while (i < args.length) { int placeholderStart = template.indexOf("%s", templateStart); if (placeholderStart == -1) { break; } builder.append(template.substring(templateStart, placeholderStart)); builder.append(args[i++]); templateStart = placeholderStart + 2; } builder.append(template.substring(templateStart)); // if we run out of placeholders, append the extra args in square braces if (i < args.length) { builder.append(" ["); builder.append(args[i++]); while (i < args.length) { builder.append(", "); builder.append(args[i++]); } builder.append("]"); } return builder.toString(); } } guice-3.0/core/src/com/google/inject/internal/util/LineNumbers.java0000644000175000017500000001646411526022356025265 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.Map; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Attribute; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; /** * Looks up line numbers for classes and their members. * * @author Chris Nokleberg */ final class LineNumbers { private final Class type; private final Map lines = Maps.newHashMap(); private String source; private int firstLine = Integer.MAX_VALUE; /** * Reads line number information from the given class, if available. * * @param type the class to read line number information from * @throws IllegalArgumentException if the bytecode for the class cannot be found * @throws java.io.IOException if an error occurs while reading bytecode */ public LineNumbers(Class type) throws IOException { this.type = type; if (!type.isArray()) { InputStream in = type.getResourceAsStream("/" + type.getName().replace('.', '/') + ".class"); if (in != null) { new ClassReader(in).accept(new LineNumberReader(), ClassReader.SKIP_FRAMES); } } } /** * Get the source file name as read from the bytecode. * * @return the source file name if available, or null */ public String getSource() { return source; } /** * Get the line number associated with the given member. * * @param member a field, constructor, or method belonging to the class used during construction * @return the wrapped line number, or null if not available * @throws IllegalArgumentException if the member does not belong to the class used during * construction */ public Integer getLineNumber(Member member) { Preconditions.checkArgument(type == member.getDeclaringClass(), "Member %s belongs to %s, not %s", member, member.getDeclaringClass(), type); return lines.get(memberKey(member)); } /** Gets the first line number. */ public int getFirstLine() { return firstLine == Integer.MAX_VALUE ? 1 : firstLine; } private String memberKey(Member member) { checkNotNull(member, "member"); /*if[AOP]*/ if (member instanceof Field) { return member.getName(); } else if (member instanceof Method) { return member.getName() + org.objectweb.asm.Type.getMethodDescriptor((Method) member); } else if (member instanceof Constructor) { StringBuilder sb = new StringBuilder().append("("); for (Class param : ((Constructor) member).getParameterTypes()) { sb.append(org.objectweb.asm.Type.getDescriptor(param)); } return sb.append(")V").toString(); } else { throw new IllegalArgumentException( "Unsupported implementation class for Member, " + member.getClass()); } /*end[AOP]*/ /*if[NO_AOP] return ""; end[NO_AOP]*/ } private class LineNumberReader implements ClassVisitor, MethodVisitor, AnnotationVisitor { private int line = -1; private String pendingMethod; private String name; public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { this.name = name; } public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { if ((access & Opcodes.ACC_PRIVATE) != 0) { return null; } pendingMethod = name + desc; line = -1; return this; } public void visitSource(String source, String debug) { LineNumbers.this.source = source; } public void visitLineNumber(int line, Label start) { if (line < firstLine) { firstLine = line; } this.line = line; if (pendingMethod != null) { lines.put(pendingMethod, line); pendingMethod = null; } } public void visitFieldInsn(int opcode, String owner, String name, String desc) { if (opcode == Opcodes.PUTFIELD && this.name.equals(owner) && !lines.containsKey(name) && line != -1) { lines.put(name, line); } } public void visitEnd() { } public void visitInnerClass(String name, String outerName, String innerName, int access) { } public void visitOuterClass(String owner, String name, String desc) { } public void visitAttribute(Attribute attr) { } public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { return null; } public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return this; } public AnnotationVisitor visitAnnotation(String name, String desc) { return this; } public AnnotationVisitor visitAnnotationDefault() { return this; } public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { return this; } public AnnotationVisitor visitArray(String name) { return this; } public void visitEnum(String name, String desc, String value) { } public void visit(String name, Object value) { } public void visitCode() { } public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { } public void visitIincInsn(int var, int increment) { } public void visitInsn(int opcode) { } public void visitIntInsn(int opcode, int operand) { } public void visitJumpInsn(int opcode, Label label) { } public void visitLabel(Label label) { } public void visitLdcInsn(Object cst) { } public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { } public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { } public void visitMaxs(int maxStack, int maxLocals) { } public void visitMethodInsn(int opcode, String owner, String name, String desc) { } public void visitMultiANewArrayInsn(String desc, int dims) { } public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { } public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { } public void visitTypeInsn(int opcode, String desc) { } public void visitVarInsn(int opcode, int var) { } } } guice-3.0/core/src/com/google/inject/internal/util/ToStringBuilder.java0000644000175000017500000000247211460132776026121 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.LinkedHashMap; import java.util.Map; /** * Helps with {@code toString()} methods. * * @author crazybob@google.com (Bob Lee) */ public class ToStringBuilder { // Linked hash map ensures ordering. final Map map = new LinkedHashMap(); final String name; public ToStringBuilder(Class type) { this.name = type.getSimpleName(); } public ToStringBuilder add(String name, Object value) { if (map.put(name, value) != null) { throw new RuntimeException("Duplicate names: " + name); } return this; } @Override public String toString() { return name + map.toString().replace('{', '[').replace('}', ']'); } } guice-3.0/core/src/com/google/inject/internal/util/Hashing.java0000644000175000017500000000341711460132776024422 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; /** * Static methods for implementing hash-based collections. * * @author Kevin Bourrillion * @author Jesse Wilson */ final class Hashing { private Hashing() {} /* * This method was written by Doug Lea with assistance from members of JCP * JSR-166 Expert Group and released to the public domain, as explained at * http://creativecommons.org/licenses/publicdomain */ static int smear(int hashCode) { hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12); return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4); } // We use power-of-2 tables, and this is the highest int that's a power of 2 private static final int MAX_TABLE_SIZE = 1 << 30; // If the set has this many elements, it will "max out" the table size private static final int CUTOFF = 1 << 29; // Size the table to be at most 50% full, if possible static int chooseTableSize(int setSize) { if (setSize < CUTOFF) { return Integer.highestOneBit(setSize) << 2; } // The table can't be completely full or we'll get infinite reprobes Preconditions.checkArgument(setSize < MAX_TABLE_SIZE, "collection too large"); return MAX_TABLE_SIZE; } } guice-3.0/core/src/com/google/inject/internal/util/AbstractMapEntry.java0000644000175000017500000000402211461631440026246 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Map.Entry; /** * Implementation of the {@code equals}, {@code hashCode}, and {@code toString} * methods of {@code Entry}. * * @author Jared Levy */ public abstract class AbstractMapEntry implements Entry { public abstract K getKey(); public abstract V getValue(); /** * {@inheritDoc} * *

This implementation throws an {@link UnsupportedOperationException}. * Override this method to support mutable map entries. */ public V setValue(V value) { throw new UnsupportedOperationException(); } /** * Indicates whether an object equals this entry, following the behavior * specified in {@link Entry#equals}. */ @Override public boolean equals(@Nullable Object object) { if (object instanceof Entry) { Entry that = (Entry) object; return Objects.equal(this.getKey(), that.getKey()) && Objects.equal(this.getValue(), that.getValue()); } return false; } /** * Return this entry's hash code, following the behavior specified in * {@link Entry#hashCode}. */ @Override public int hashCode() { K k = getKey(); V v = getValue(); return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode()); } /** * Returns a string representation of the form {key}={value}. */ @Override public String toString() { return getKey() + "=" + getValue(); } } guice-3.0/core/src/com/google/inject/internal/util/Function.java0000644000175000017500000000457711461631440024627 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; /** * A transformation from one object to another. For example, a * {@code StringToIntegerFunction} may implement * Function<String,Integer> and transform integers in * {@code String} format to {@code Integer} format. * *

The transformation on the source object does not necessarily result in * an object of a different type. For example, a * {@code FarenheitToCelsiusFunction} may implement * Function<Float,Float>. * *

Implementations which may cause side effects upon evaluation are strongly * encouraged to state this fact clearly in their API documentation. * *

This interface may be used with the Google Web Toolkit (GWT). * * @param the type of the function input * @param the type of the function output * @author Kevin Bourrillion * @author Scott Bonneau */ public interface Function { /** * Applies the function to an object of type {@code F}, resulting in an object * of type {@code T}. Note that types {@code F} and {@code T} may or may not * be the same. * * @param from the source object * @return the resulting object */ T apply(@Nullable F from); /** * Indicates whether some other object is equal to this {@code Function}. * This method can return {@code true} only if the specified object is * also a {@code Function} and, for every input object {@code o}, it returns * exactly the same value. Thus, {@code function1.equals(function2)} implies * that either {@code function1.apply(o)} and {@code function2.apply(o)} are * both null, or {@code function1.apply(o).equals(function2.apply(o))}. * *

Note that it is always safe not to override * {@link Object#equals}. */ boolean equals(@Nullable Object obj); } guice-3.0/core/src/com/google/inject/internal/util/ObjectArrays.java0000644000175000017500000000250611460132776025427 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.lang.reflect.Array; /** * Static utility methods pertaining to object arrays. * * @author Kevin Bourrillion */ public final class ObjectArrays { private ObjectArrays() {} /** * Returns a new array of the given length with the same type as a reference * array. * * @param reference any array of the desired type * @param length the length of the new array */ public static T[] newArray(T[] reference, int length) { Class type = reference.getClass().getComponentType(); // the cast is safe because result.getClass() == reference.getClass() @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(type, length); return result; } } guice-3.0/core/src/com/google/inject/internal/util/Sets.java0000644000175000017500000001374711461631440023757 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; import java.util.AbstractSet; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; /** * Static utility methods pertaining to {@link Set} instances. Also see this * class's counterparts {@link Lists} and {@link Maps}. * * @author Kevin Bourrillion * @author Jared Levy */ public final class Sets { private Sets() {} // HashSet /** * Creates an empty {@code HashSet} instance. * *

Note: if {@code E} is an {@link Enum} type, use {@link * EnumSet#noneOf} instead. * *

Note: if you need an immutable empty Set, use {@link * Collections#emptySet} instead. * * @return a newly created, empty {@code HashSet} */ public static HashSet newHashSet() { return new HashSet(); } // TODO: Modify the sets returned by newConcurrentHashSet so calling // remove(null) on them doesn't throw an NPE. // LinkedHashSet /** * Creates an empty {@code LinkedHashSet} instance. * * @return a newly created, empty {@code LinkedHashSet} */ public static LinkedHashSet newLinkedHashSet() { return new LinkedHashSet(); } /* * Regarding newSetForMap() and SetFromMap: * * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at * http://creativecommons.org/licenses/publicdomain */ /** * Returns a set backed by the specified map. The resulting set displays * the same ordering, concurrency, and performance characteristics as the * backing map. In essence, this factory method provides a {@link Set} * implementation corresponding to any {@link Map} implementation. There is no * need to use this method on a {@link Map} implementation that already has a * corresponding {@link Set} implementation (such as {@link HashMap} or * {@link TreeMap}). * *

Each method invocation on the set returned by this method results in * exactly one method invocation on the backing map or its keySet * view, with one exception. The addAll method is implemented as a * sequence of put invocations on the backing map. * *

The specified map must be empty at the time this method is invoked, * and should not be accessed directly after this method returns. These * conditions are ensured if the map is created empty, passed directly * to this method, and no reference to the map is retained, as illustrated * in the following code fragment: *

   *    Set<Object> identityHashSet = Sets.newSetFromMap(
   *        new IdentityHashMap<Object, Boolean>()); 
* * This method has the same behavior as the JDK 6 method * {@code Collections.newSetFromMap()}. The returned set is serializable if * the backing map is. * * @param map the backing map * @return the set backed by the map * @throws IllegalArgumentException if map is not empty */ public static Set newSetFromMap(Map map) { return new SetFromMap(map); } private static class SetFromMap extends AbstractSet implements Set, Serializable { private final Map m; // The backing map private transient Set s; // Its keySet SetFromMap(Map map) { Preconditions.checkArgument(map.isEmpty(), "Map is non-empty"); m = map; s = map.keySet(); } @Override public void clear() { m.clear(); } @Override public int size() { return m.size(); } @Override public boolean isEmpty() { return m.isEmpty(); } @Override public boolean contains(Object o) { return m.containsKey(o); } @Override public boolean remove(Object o) { return m.remove(o) != null; } @Override public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; } @Override public Iterator iterator() { return s.iterator(); } @Override public Object[] toArray() { return s.toArray(); } @Override public T[] toArray(T[] a) { return s.toArray(a); } @Override public String toString() { return s.toString(); } @Override public int hashCode() { return s.hashCode(); } @Override public boolean equals(@Nullable Object object) { return this == object || this.s.equals(object); } @Override public boolean containsAll(Collection c) { return s.containsAll(c); } @Override public boolean removeAll(Collection c) { return s.removeAll(c); } @Override public boolean retainAll(Collection c) { return s.retainAll(c); } // addAll is the only inherited implementation static final long serialVersionUID = 0; private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); s = m.keySet(); } } /** * Calculates and returns the hash code of {@code s}. */ static int hashCodeImpl(Set s) { int hashCode = 0; for (Object o : s) { hashCode += o != null ? o.hashCode() : 0; } return hashCode; } } guice-3.0/core/src/com/google/inject/internal/util/Finalizer.java0000644000175000017500000001443311460132776024764 0ustar drazzibdrazzib/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.util.logging.Level; import java.util.logging.Logger; /** * Thread that finalizes referents. All references should implement * {@code com.google.inject.internal.FinalizableReference}. * *

While this class is public, we consider it to be *internal* and not part * of our published API. It is public so we can access it reflectively across * class loaders in secure environments. * *

This class can't depend on other Google Collections code. If we were * to load this class in the same class loader as the rest of * Google Collections, this thread would keep an indirect strong reference * to the class loader and prevent it from being garbage collected. This * poses a problem for environments where you want to throw away the class * loader. For example, dynamically reloading a web application or unloading * an OSGi bundle. * *

{@code com.google.inject.internal.FinalizableReferenceQueue} loads this class * in its own class loader. That way, this class doesn't prevent the main * class loader from getting garbage collected, and this class can detect when * the main class loader has been garbage collected and stop itself. */ public class Finalizer extends Thread { private static final Logger logger = Logger.getLogger(Finalizer.class.getName()); /** Name of FinalizableReference.class. */ private static final String FINALIZABLE_REFERENCE = "com.google.inject.internal.util.FinalizableReference"; /** * Starts the Finalizer thread. FinalizableReferenceQueue calls this method * reflectively. * * @param finalizableReferenceClass FinalizableReference.class * @param frq reference to instance of FinalizableReferenceQueue that started * this thread * @return ReferenceQueue which Finalizer will poll */ public static ReferenceQueue startFinalizer( Class finalizableReferenceClass, Object frq) { /* * We use FinalizableReference.class for two things: * * 1) To invoke FinalizableReference.finalizeReferent() * * 2) To detect when FinalizableReference's class loader has to be garbage * collected, at which point, Finalizer can stop running */ if (!finalizableReferenceClass.getName().equals(FINALIZABLE_REFERENCE)) { throw new IllegalArgumentException( "Expected " + FINALIZABLE_REFERENCE + "."); } Finalizer finalizer = new Finalizer(finalizableReferenceClass, frq); finalizer.start(); return finalizer.queue; } private final WeakReference> finalizableReferenceClassReference; private final PhantomReference frqReference; private final ReferenceQueue queue = new ReferenceQueue(); /** Constructs a new finalizer thread. */ private Finalizer(Class finalizableReferenceClass, Object frq) { super(Finalizer.class.getName()); this.finalizableReferenceClassReference = new WeakReference>(finalizableReferenceClass); // Keep track of the FRQ that started us so we know when to stop. this.frqReference = new PhantomReference(frq, queue); setDaemon(true); // TODO: Priority? } /** * Loops continuously, pulling references off the queue and cleaning them up. */ @SuppressWarnings("InfiniteLoopStatement") @Override public void run() { try { while (true) { try { cleanUp(queue.remove()); } catch (InterruptedException e) { /* ignore */ } } } catch (ShutDown shutDown) { /* ignore */ } } /** * Cleans up a single reference. Catches and logs all throwables. */ private void cleanUp(Reference reference) throws ShutDown { Method finalizeReferentMethod = getFinalizeReferentMethod(); do { /* * This is for the benefit of phantom references. Weak and soft * references will have already been cleared by this point. */ reference.clear(); if (reference == frqReference) { /* * The client no longer has a reference to the * FinalizableReferenceQueue. We can stop. */ throw new ShutDown(); } try { finalizeReferentMethod.invoke(reference); } catch (Throwable t) { logger.log(Level.SEVERE, "Error cleaning up after reference.", t); } /* * Loop as long as we have references available so as not to waste * CPU looking up the Method over and over again. */ } while ((reference = queue.poll()) != null); } /** * Looks up FinalizableReference.finalizeReferent() method. */ private Method getFinalizeReferentMethod() throws ShutDown { Class finalizableReferenceClass = finalizableReferenceClassReference.get(); if (finalizableReferenceClass == null) { /* * FinalizableReference's class loader was reclaimed. While there's a * chance that other finalizable references could be enqueued * subsequently (at which point the class loader would be resurrected * by virtue of us having a strong reference to it), we should pretty * much just shut down and make sure we don't keep it alive any longer * than necessary. */ throw new ShutDown(); } try { return finalizableReferenceClass.getMethod("finalizeReferent"); } catch (NoSuchMethodException e) { throw new AssertionError(e); } } /** Indicates that it's time to shut down the Finalizer. */ @SuppressWarnings("serial") // Never serialized or thrown out of this class. private static class ShutDown extends Exception { } } guice-3.0/core/src/com/google/inject/internal/util/Maps.java0000644000175000017500000000527111461631440023732 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; /** * Static utility methods pertaining to {@link Map} instances. Also see this * class's counterparts {@link Lists} and {@link Sets}. * * @author Kevin Bourrillion * @author Mike Bostock * @author Isaac Shum */ public final class Maps { private Maps() {} /** * Creates a {@code HashMap} instance. * *

Note: if you don't actually need the resulting map to be mutable, * use {@link Collections#emptyMap} instead. * * @return a new, empty {@code HashMap} */ public static HashMap newHashMap() { return new HashMap(); } /** * Creates an insertion-ordered {@code LinkedHashMap} instance. * * @return a new, empty {@code LinkedHashMap} */ public static LinkedHashMap newLinkedHashMap() { return new LinkedHashMap(); } /** * Creates a {@code TreeMap} instance using the natural ordering of its * elements. * * @return a new, empty {@code TreeMap} */ @SuppressWarnings("unchecked") // allow ungenerified Comparable types public static TreeMap newTreeMap() { return new TreeMap(); } /** * Creates an {@code IdentityHashMap} instance. * * @return a new, empty {@code IdentityHashMap} */ public static IdentityHashMap newIdentityHashMap() { return new IdentityHashMap(); } /** * Returns an immutable map entry with the specified key and value. The {@link * Entry#setValue} operation throws an {@link UnsupportedOperationException}. * *

The returned entry is serializable. * * @param key the key to be associated with the returned entry * @param value the value to be associated with the returned entry */ public static Entry immutableEntry( @Nullable final K key, @Nullable final V value) { return new ImmutableEntry(key, value); } } guice-3.0/core/src/com/google/inject/internal/util/FinalizableReference.java0000644000175000017500000000213611460132776027075 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; /** * Implemented by references that have code to run after garbage collection of * their referents. * * @see FinalizableReferenceQueue * @author Bob Lee */ public interface FinalizableReference { /** * Invoked on a background thread after the referent has been garbage * collected unless security restictions prevented starting a background * thread, in which case this method is invoked when new references * are created. */ void finalizeReferent(); } guice-3.0/core/src/com/google/inject/internal/util/Join.java0000644000175000017500000003035511461631440023732 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.io.IOException; import java.util.Arrays; import java.util.Iterator; import java.util.Map; /** * Utility for joining pieces of text separated by a delimiter. It can handle * iterators, collections, arrays, and varargs, and can append to any * {@link Appendable} or just return a {@link String}. For example, * {@code join(":", "a", "b", "c")} returns {@code "a:b:c"}. * *

All methods of this class throw {@link NullPointerException} when a value * of {@code null} is supplied for any parameter. The elements within the * collection, iterator, array, or varargs parameter list may be null -- * these will be represented in the output by the string {@code "null"}. * * @author Kevin Bourrillion */ public final class Join { private Join() {} /** * Returns a string containing the {@code tokens}, converted to strings if * necessary, separated by {@code delimiter}. If {@code tokens} is empty, it * returns an empty string. * *

Each token will be converted to a {@link CharSequence} using * {@link String#valueOf(Object)}, if it isn't a {@link CharSequence} already. * Note that this implies that null tokens will be appended as the * four-character string {@code "null"}. * * @param delimiter a string to append between every element, but not at the * beginning or end * @param tokens objects to append * @return a string consisting of the joined elements */ public static String join(String delimiter, Iterable tokens) { return join(delimiter, tokens.iterator()); } /** * Returns a string containing the {@code tokens}, converted to strings if * necessary, separated by {@code delimiter}. If {@code tokens} is empty, it * returns an empty string. * *

Each token will be converted to a {@link CharSequence} using * {@link String#valueOf(Object)}, if it isn't a {@link CharSequence} already. * Note that this implies that null tokens will be appended as the * four-character string {@code "null"}. * * @param delimiter a string to append between every element, but not at the * beginning or end * @param tokens objects to append * @return a string consisting of the joined elements */ public static String join(String delimiter, Object[] tokens) { return join(delimiter, Arrays.asList(tokens)); } /** * Returns a string containing the {@code tokens}, converted to strings if * necessary, separated by {@code delimiter}. * *

Each token will be converted to a {@link CharSequence} using * {@link String#valueOf(Object)}, if it isn't a {@link CharSequence} already. * Note that this implies that null tokens will be appended as the * four-character string {@code "null"}. * * @param delimiter a string to append between every element, but not at the * beginning or end * @param firstToken the first object to append * @param otherTokens subsequent objects to append * @return a string consisting of the joined elements */ public static String join( String delimiter, @Nullable Object firstToken, Object... otherTokens) { Preconditions.checkNotNull(otherTokens); return join(delimiter, Lists.newArrayList(firstToken, otherTokens)); } /** * Returns a string containing the {@code tokens}, converted to strings if * necessary, separated by {@code delimiter}. If {@code tokens} is empty, it * returns an empty string. * *

Each token will be converted to a {@link CharSequence} using * {@link String#valueOf(Object)}, if it isn't a {@link CharSequence} already. * Note that this implies that null tokens will be appended as the * four-character string {@code "null"}. * * @param delimiter a string to append between every element, but not at the * beginning or end * @param tokens objects to append * @return a string consisting of the joined elements */ public static String join(String delimiter, Iterator tokens) { StringBuilder sb = new StringBuilder(); join(sb, delimiter, tokens); return sb.toString(); } /** * Returns a string containing the contents of {@code map}, with entries * separated by {@code entryDelimiter}, and keys and values separated with * {@code keyValueSeparator}. * *

Each key and value will be converted to a {@link CharSequence} using * {@link String#valueOf(Object)}, if it isn't a {@link CharSequence} already. * Note that this implies that null tokens will be appended as the * four-character string {@code "null"}. * * @param keyValueSeparator a string to append between every key and its * associated value * @param entryDelimiter a string to append between every entry, but not at * the beginning or end * @param map the map containing the data to join * @return a string consisting of the joined entries of the map; empty if the * map is empty */ public static String join( String keyValueSeparator, String entryDelimiter, Map map) { return join(new StringBuilder(), keyValueSeparator, entryDelimiter, map) .toString(); } /** * Appends each of the {@code tokens} to {@code appendable}, separated by * {@code delimiter}. * *

Each token will be converted to a {@link CharSequence} using * {@link String#valueOf(Object)}, if it isn't a {@link CharSequence} already. * Note that this implies that null tokens will be appended as the * four-character string {@code "null"}. * * @param appendable the object to append the results to * @param delimiter a string to append between every element, but not at the * beginning or end * @param tokens objects to append * @return the same {@code Appendable} instance that was passed in * @throws JoinException if an {@link IOException} occurs */ public static T join( T appendable, String delimiter, Iterable tokens) { return join(appendable, delimiter, tokens.iterator()); } /** * Appends each of the {@code tokens} to {@code appendable}, separated by * {@code delimiter}. * *

Each token will be converted to a {@link CharSequence} using * {@link String#valueOf(Object)}, if it isn't a {@link CharSequence} already. * Note that this implies that null tokens will be appended as the * four-character string {@code "null"}. * * @param appendable the object to append the results to * @param delimiter a string to append between every element, but not at the * beginning or end * @param tokens objects to append * @return the same {@code Appendable} instance that was passed in * @throws JoinException if an {@link IOException} occurs */ public static T join( T appendable, String delimiter, Object[] tokens) { return join(appendable, delimiter, Arrays.asList(tokens)); } /** * Appends each of the {@code tokens} to {@code appendable}, separated by * {@code delimiter}. * *

Each token will be converted to a {@link CharSequence} using * {@link String#valueOf(Object)}, if it isn't a {@link CharSequence} already. * Note that this implies that null tokens will be appended as the * four-character string {@code "null"}. * * @param appendable the object to append the results to * @param delimiter a string to append between every element, but not at the * beginning or end * @param firstToken the first object to append * @param otherTokens subsequent objects to append * @return the same {@code Appendable} instance that was passed in * @throws JoinException if an {@link IOException} occurs */ public static T join(T appendable, String delimiter, @Nullable Object firstToken, Object... otherTokens) { Preconditions.checkNotNull(otherTokens); return join(appendable, delimiter, Lists.newArrayList(firstToken, otherTokens)); } /** * Appends each of the {@code tokens} to {@code appendable}, separated by * {@code delimiter}. * *

Each token will be converted to a {@link CharSequence} using * {@link String#valueOf(Object)}, if it isn't a {@link CharSequence} already. * Note that this implies that null tokens will be appended as the * four-character string {@code "null"}. * * @param appendable the object to append the results to * @param delimiter a string to append between every element, but not at the * beginning or end * @param tokens objects to append * @return the same {@code Appendable} instance that was passed in * @throws JoinException if an {@link IOException} occurs */ public static T join( T appendable, String delimiter, Iterator tokens) { /* This method is the workhorse of the class */ Preconditions.checkNotNull(appendable); Preconditions.checkNotNull(delimiter); if (tokens.hasNext()) { try { appendOneToken(appendable, tokens.next()); while (tokens.hasNext()) { appendable.append(delimiter); appendOneToken(appendable, tokens.next()); } } catch (IOException e) { throw new JoinException(e); } } return appendable; } /** * Appends the contents of {@code map} to {@code appendable}, with entries * separated by {@code entryDelimiter}, and keys and values separated with * {@code keyValueSeparator}. * *

Each key and value will be converted to a {@link CharSequence} using * {@link String#valueOf(Object)}, if it isn't a {@link CharSequence} already. * Note that this implies that null tokens will be appended as the * four-character string {@code "null"}. * * @param appendable the object to append the results to * @param keyValueSeparator a string to append between every key and its * associated value * @param entryDelimiter a string to append between every entry, but not at * the beginning or end * @param map the map containing the data to join * @return the same {@code Appendable} instance that was passed in */ public static T join(T appendable, String keyValueSeparator, String entryDelimiter, Map map) { Preconditions.checkNotNull(appendable); Preconditions.checkNotNull(keyValueSeparator); Preconditions.checkNotNull(entryDelimiter); Iterator> entries = map.entrySet().iterator(); if (entries.hasNext()) { try { appendOneEntry(appendable, keyValueSeparator, entries.next()); while (entries.hasNext()) { appendable.append(entryDelimiter); appendOneEntry(appendable, keyValueSeparator, entries.next()); } } catch (IOException e) { throw new JoinException(e); } } return appendable; } private static void appendOneEntry( Appendable appendable, String keyValueSeparator, Map.Entry entry) throws IOException { appendOneToken(appendable, entry.getKey()); appendable.append(keyValueSeparator); appendOneToken(appendable, entry.getValue()); } private static void appendOneToken(Appendable appendable, Object token) throws IOException { appendable.append(toCharSequence(token)); } private static CharSequence toCharSequence(Object token) { return (token instanceof CharSequence) ? (CharSequence) token : String.valueOf(token); } /** * Exception thrown in response to an {@link IOException} from the supplied * {@link Appendable}. This is used because most callers won't want to * worry about catching an IOException. */ public static class JoinException extends RuntimeException { private JoinException(IOException cause) { super(cause); } private static final long serialVersionUID = 1L; } }guice-3.0/core/src/com/google/inject/internal/util/SourceProvider.java0000644000175000017500000000423411460132776026012 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import static com.google.inject.internal.util.Iterables.concat; import java.util.List; /** * Provides access to the calling line of code. * * @author crazybob@google.com (Bob Lee) */ public final class SourceProvider { /** Indicates that the source is unknown. */ public static final Object UNKNOWN_SOURCE = "[unknown source]"; private final ImmutableSet classNamesToSkip; public static final SourceProvider DEFAULT_INSTANCE = new SourceProvider(ImmutableSet.of(SourceProvider.class.getName())); private SourceProvider(Iterable classesToSkip) { this.classNamesToSkip = ImmutableSet.copyOf(classesToSkip); } /** Returns a new instance that also skips {@code moreClassesToSkip}. */ public SourceProvider plusSkippedClasses(Class... moreClassesToSkip) { return new SourceProvider(concat(classNamesToSkip, asStrings(moreClassesToSkip))); } /** Returns the class names as Strings */ private static List asStrings(Class... classes) { List strings = Lists.newArrayList(); for (Class c : classes) { strings.add(c.getName()); } return strings; } /** * Returns the calling line of code. The selected line is the nearest to the top of the stack that * is not skipped. */ public StackTraceElement get() { for (final StackTraceElement element : new Throwable().getStackTrace()) { String className = element.getClassName(); if (!classNamesToSkip.contains(className)) { return element; } } throw new AssertionError(); } } guice-3.0/core/src/com/google/inject/internal/util/Iterables.java0000644000175000017500000001105011460132776024743 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; /** * This class contains static utility methods that operate on or return objects * of type {@code Iterable}. Also see the parallel implementations in {@link * Iterators}. * * @author Kevin Bourrillion * @author Scott Bonneau */ public final class Iterables { private Iterables() {} /** * Returns a string representation of {@code iterable}, with the format * {@code [e1, e2, ..., en]}. */ public static String toString(Iterable iterable) { return Iterators.toString(iterable.iterator()); } /** * Returns the single element contained in {@code iterable}. * * @throws NoSuchElementException if the iterable is empty * @throws IllegalArgumentException if the iterable contains multiple * elements */ public static T getOnlyElement(Iterable iterable) { return Iterators.getOnlyElement(iterable.iterator()); } /** * Combines two iterables into a single iterable. The returned iterable has an * iterator that traverses the elements in {@code a}, followed by the elements * in {@code b}. The source iterators are not polled until necessary. * *

The returned iterable's iterator supports {@code remove()} when the * corresponding input iterator supports it. */ @SuppressWarnings("unchecked") public static Iterable concat( Iterable a, Iterable b) { Preconditions.checkNotNull(a); Preconditions.checkNotNull(b); return concat(Arrays.asList(a, b)); } /** * Combines multiple iterables into a single iterable. The returned iterable * has an iterator that traverses the elements of each iterable in * {@code inputs}. The input iterators are not polled until necessary. * *

The returned iterable's iterator supports {@code remove()} when the * corresponding input iterator supports it. The methods of the returned * iterable may throw {@code NullPointerException} if any of the input * iterators are null. */ public static Iterable concat( Iterable> inputs) { /* * Hint: if you let A represent Iterable and B represent * Iterator, then this Function would look simply like: * * Function function = new Function { * public B apply(A from) { * return from.iterator(); * } * } * * TODO: there may be a better way to do this. */ Function, Iterator> function = new Function, Iterator>() { public Iterator apply(Iterable from) { return from.iterator(); } }; final Iterable> iterators = transform(inputs, function); return new IterableWithToString() { public Iterator iterator() { return Iterators.concat(iterators.iterator()); } }; } /** * Returns an iterable that applies {@code function} to each element of {@code * fromIterable}. * *

The returned iterable's iterator supports {@code remove()} if the * provided iterator does. After a successful {@code remove()} call, * {@code fromIterable} no longer contains the corresponding element. */ public static Iterable transform(final Iterable fromIterable, final Function function) { Preconditions.checkNotNull(fromIterable); Preconditions.checkNotNull(function); return new IterableWithToString() { public Iterator iterator() { return Iterators.transform(fromIterable.iterator(), function); } }; } // Methods only in Iterables, not in Iterators abstract static class IterableWithToString implements Iterable { @Override public String toString() { return Iterables.toString(this); } } } guice-3.0/core/src/com/google/inject/internal/util/ExpirationTimer.java0000644000175000017500000000142411460132776026160 0ustar drazzibdrazzib/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.util.Timer; /** * Timer used for entry expiration in MapMaker. */ class ExpirationTimer { static Timer instance = new Timer(true); } guice-3.0/core/src/com/google/inject/internal/util/FinalizableSoftReference.java0000644000175000017500000000251611460132776027733 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.lang.ref.SoftReference; /** * Soft reference with a {@code finalizeReferent()} method which a background * thread invokes after the garbage collector reclaims the referent. This is a * simpler alternative to using a {@link java.lang.ref.ReferenceQueue}. * * @author Bob Lee */ public abstract class FinalizableSoftReference extends SoftReference implements FinalizableReference { /** * Consructs a new finalizable soft reference. * * @param referent to softly reference * @param queue that should finalize the referent */ protected FinalizableSoftReference(T referent, FinalizableReferenceQueue queue) { super(referent, queue.queue); queue.cleanUp(); } } guice-3.0/core/src/com/google/inject/internal/util/FinalizableWeakReference.java0000644000175000017500000000251611460132776027707 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.lang.ref.WeakReference; /** * Weak reference with a {@code finalizeReferent()} method which a background * thread invokes after the garbage collector reclaims the referent. This is a * simpler alternative to using a {@link java.lang.ref.ReferenceQueue}. * * @author Bob Lee */ public abstract class FinalizableWeakReference extends WeakReference implements FinalizableReference { /** * Consructs a new finalizable weak reference. * * @param referent to weakly reference * @param queue that should finalize the referent */ protected FinalizableWeakReference(T referent, FinalizableReferenceQueue queue) { super(referent, queue.queue); queue.cleanUp(); } } guice-3.0/core/src/com/google/inject/internal/util/ComputationException.java0000644000175000017500000000150611460132776027217 0ustar drazzibdrazzib/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; /** * Wraps an exception that occured during a computation. */ public class ComputationException extends RuntimeException { public ComputationException(Throwable cause) { super(cause); } } guice-3.0/core/src/com/google/inject/internal/util/FinalizablePhantomReference.java0000644000175000017500000000270211460132776030423 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal.util; import java.lang.ref.PhantomReference; /** * Phantom reference with a {@code finalizeReferent()} method which a * background thread invokes after the garbage collector reclaims the * referent. This is a simpler alternative to using a {@link * java.lang.ref.ReferenceQueue}. * *

Unlike a normal phantom reference, this reference will be cleared * automatically. * * @author Bob Lee */ public abstract class FinalizablePhantomReference extends PhantomReference implements FinalizableReference { /** * Constructs a new finalizable phantom reference. * * @param referent to phantom reference * @param queue that should finalize the referent */ protected FinalizablePhantomReference(T referent, FinalizableReferenceQueue queue) { super(referent, queue.queue); queue.cleanUp(); } } guice-3.0/core/src/com/google/inject/internal/ErrorHandler.java0000644000175000017500000000166511460133000024433 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.spi.Message; /** * Handles errors in the Injector. * * @author crazybob@google.com (Bob Lee) */ interface ErrorHandler { /** * Handles an error. */ void handle(Object source, Errors errors); /** * Handles a user-reported error. */ void handle(Message message); } guice-3.0/core/src/com/google/inject/internal/InjectorImpl.java0000644000175000017500000011364011533372514024460 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Binding; import com.google.inject.ConfigurationException; import com.google.inject.ImplementedBy; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.MembersInjector; import com.google.inject.Module; import com.google.inject.ProvidedBy; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.Scope; import com.google.inject.Stage; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Maps; import com.google.inject.internal.util.Nullable; import com.google.inject.internal.util.Objects; import com.google.inject.internal.util.SourceProvider; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.ConvertedConstantBinding; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.ProviderBinding; import com.google.inject.spi.TypeConverterBinding; import com.google.inject.util.Providers; import java.lang.annotation.Annotation; import java.lang.reflect.GenericArrayType; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Default {@link Injector} implementation. * * @author crazybob@google.com (Bob Lee) */ final class InjectorImpl implements Injector, Lookups { public static final TypeLiteral STRING_TYPE = TypeLiteral.get(String.class); /** Options that control how the injector behaves. */ static class InjectorOptions { final Stage stage; final boolean jitDisabled; final boolean disableCircularProxies; InjectorOptions(Stage stage, boolean jitDisabled, boolean disableCircularProxies) { this.stage = stage; this.jitDisabled = jitDisabled; this.disableCircularProxies = disableCircularProxies; } @Override public String toString() { return new ToStringBuilder(getClass()) .add("stage", stage) .add("jitDisabled", jitDisabled) .add("disableCircularProxies", disableCircularProxies) .toString(); } } /** some limitations on what just in time bindings are allowed. */ enum JitLimitation { /** does not allow just in time bindings */ NO_JIT, /** allows existing just in time bindings, but does not allow new ones */ EXISTING_JIT, /** allows existing just in time bindings & allows new ones to be created */ NEW_OR_EXISTING_JIT, } final State state; final InjectorImpl parent; final BindingsMultimap bindingsMultimap = new BindingsMultimap(); final InjectorOptions options; /** Just-in-time binding cache. Guarded by state.lock() */ final Map, BindingImpl> jitBindings = Maps.newHashMap(); Lookups lookups = new DeferredLookups(this); InjectorImpl(@Nullable InjectorImpl parent, State state, InjectorOptions injectorOptions) { this.parent = parent; this.state = state; this.options = injectorOptions; if (parent != null) { localContext = parent.localContext; } else { localContext = new ThreadLocal() { protected Object[] initialValue() { return new Object[1]; } }; } } /** Indexes bindings by type. */ void index() { for (Binding binding : state.getExplicitBindingsThisLevel().values()) { index(binding); } } void index(Binding binding) { bindingsMultimap.put(binding.getKey().getTypeLiteral(), binding); } public List> findBindingsByType(TypeLiteral type) { return bindingsMultimap.getAll(type); } /** Returns the binding for {@code key} */ public BindingImpl getBinding(Key key) { Errors errors = new Errors(key); try { BindingImpl result = getBindingOrThrow(key, errors, JitLimitation.EXISTING_JIT); errors.throwConfigurationExceptionIfErrorsExist(); return result; } catch (ErrorsException e) { throw new ConfigurationException(errors.merge(e.getErrors()).getMessages()); } } public BindingImpl getExistingBinding(Key key) { // Check explicit bindings, i.e. bindings created by modules. BindingImpl explicitBinding = state.getExplicitBinding(key); if (explicitBinding != null) { return explicitBinding; } synchronized (state.lock()) { // See if any jit bindings have been created for this key. for (InjectorImpl injector = this; injector != null; injector = injector.parent) { @SuppressWarnings("unchecked") BindingImpl jitBinding = (BindingImpl) injector.jitBindings.get(key); if(jitBinding != null) { return jitBinding; } } } // If Key is a Provider, we have to see if the type it is providing exists, // and, if so, we have to create the binding for the provider. if(isProvider(key)) { try { // This is safe because isProvider above ensures that T is a Provider @SuppressWarnings("unchecked") Key providedKey = (Key)getProvidedKey((Key)key, new Errors()); if(getExistingBinding(providedKey) != null) { return getBinding(key); } } catch(ErrorsException e) { throw new ConfigurationException(e.getErrors().getMessages()); } } // No existing binding exists. return null; } /** * Gets a binding implementation. First, it check to see if the parent has a binding. If the * parent has a binding and the binding is scoped, it will use that binding. Otherwise, this * checks for an explicit binding. If no explicit binding is found, it looks for a just-in-time * binding. */ BindingImpl getBindingOrThrow(Key key, Errors errors, JitLimitation jitType) throws ErrorsException { // Check explicit bindings, i.e. bindings created by modules. BindingImpl binding = state.getExplicitBinding(key); if (binding != null) { return binding; } // Look for an on-demand binding. return getJustInTimeBinding(key, errors, jitType); } public Binding getBinding(Class type) { return getBinding(Key.get(type)); } public Injector getParent() { return parent; } public Injector createChildInjector(Iterable modules) { return new InternalInjectorCreator() .parentInjector(this) .addModules(modules) .build(); } public Injector createChildInjector(Module... modules) { return createChildInjector(ImmutableList.of(modules)); } /** * Returns a just-in-time binding for {@code key}, creating it if necessary. * * @throws ErrorsException if the binding could not be created. */ private BindingImpl getJustInTimeBinding(Key key, Errors errors, JitLimitation jitType) throws ErrorsException { boolean jitOverride = isProvider(key) || isTypeLiteral(key) || isMembersInjector(key); synchronized (state.lock()) { // first try to find a JIT binding that we've already created for (InjectorImpl injector = this; injector != null; injector = injector.parent) { @SuppressWarnings("unchecked") // we only store bindings that match their key BindingImpl binding = (BindingImpl) injector.jitBindings.get(key); if (binding != null) { // If we found a JIT binding and we don't allow them, // fail. (But allow bindings created through TypeConverters.) if (options.jitDisabled && jitType == JitLimitation.NO_JIT && !jitOverride && !(binding instanceof ConvertedConstantBindingImpl)) { throw errors.jitDisabled(key).toException(); } else { return binding; } } } return createJustInTimeBindingRecursive(key, errors, options.jitDisabled, jitType); } } /** Returns true if the key type is Provider (but not a subclass of Provider). */ private static boolean isProvider(Key key) { return key.getTypeLiteral().getRawType().equals(Provider.class); } private static boolean isTypeLiteral(Key key) { return key.getTypeLiteral().getRawType().equals(TypeLiteral.class); } private static Key getProvidedKey(Key> key, Errors errors) throws ErrorsException { Type providerType = key.getTypeLiteral().getType(); // If the Provider has no type parameter (raw Provider)... if (!(providerType instanceof ParameterizedType)) { throw errors.cannotInjectRawProvider().toException(); } Type entryType = ((ParameterizedType) providerType).getActualTypeArguments()[0]; @SuppressWarnings("unchecked") // safe because T came from Key> Key providedKey = (Key) key.ofType(entryType); return providedKey; } /** Returns true if the key type is MembersInjector (but not a subclass of MembersInjector). */ private static boolean isMembersInjector(Key key) { return key.getTypeLiteral().getRawType().equals(MembersInjector.class) && !(key.getAnnotationType() != null); } private BindingImpl> createMembersInjectorBinding( Key> key, Errors errors) throws ErrorsException { Type membersInjectorType = key.getTypeLiteral().getType(); if (!(membersInjectorType instanceof ParameterizedType)) { throw errors.cannotInjectRawMembersInjector().toException(); } @SuppressWarnings("unchecked") // safe because T came from Key> TypeLiteral instanceType = (TypeLiteral) TypeLiteral.get( ((ParameterizedType) membersInjectorType).getActualTypeArguments()[0]); MembersInjector membersInjector = membersInjectorStore.get(instanceType, errors); InternalFactory> factory = new ConstantFactory>( Initializables.of(membersInjector)); return new InstanceBindingImpl>(this, key, SourceProvider.UNKNOWN_SOURCE, factory, ImmutableSet.of(), membersInjector); } /** * Creates a synthetic binding to {@code Provider}, i.e. a binding to the provider from * {@code Binding}. */ private BindingImpl> createProviderBinding(Key> key, Errors errors) throws ErrorsException { Key providedKey = getProvidedKey(key, errors); BindingImpl delegate = getBindingOrThrow(providedKey, errors, JitLimitation.NO_JIT); return new ProviderBindingImpl(this, key, delegate); } private static class ProviderBindingImpl extends BindingImpl> implements ProviderBinding>, HasDependencies { final BindingImpl providedBinding; ProviderBindingImpl(InjectorImpl injector, Key> key, Binding providedBinding) { super(injector, key, providedBinding.getSource(), createInternalFactory(providedBinding), Scoping.UNSCOPED); this.providedBinding = (BindingImpl) providedBinding; } static InternalFactory> createInternalFactory(Binding providedBinding) { final Provider provider = providedBinding.getProvider(); return new InternalFactory>() { public Provider get(Errors errors, InternalContext context, Dependency dependency, boolean linked) { return provider; } }; } public Key getProvidedKey() { return providedBinding.getKey(); } public V acceptTargetVisitor(BindingTargetVisitor, V> visitor) { return visitor.visit(this); } public void applyTo(Binder binder) { throw new UnsupportedOperationException("This element represents a synthetic binding."); } @Override public String toString() { return new ToStringBuilder(ProviderBinding.class) .add("key", getKey()) .add("providedKey", getProvidedKey()) .toString(); } public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(getProvidedKey())); } @Override public boolean equals(Object obj) { if(obj instanceof ProviderBindingImpl) { ProviderBindingImpl o = (ProviderBindingImpl)obj; return getKey().equals(o.getKey()) && getScoping().equals(o.getScoping()) && Objects.equal(providedBinding, o.providedBinding); } else { return false; } } @Override public int hashCode() { return Objects.hashCode(getKey(), getScoping(), providedBinding); } } /** * Converts a constant string binding to the required type. * * @return the binding if it could be resolved, or null if the binding doesn't exist * @throws com.google.inject.internal.ErrorsException if there was an error resolving the binding */ private BindingImpl convertConstantStringBinding(Key key, Errors errors) throws ErrorsException { // Find a constant string binding. Key stringKey = key.ofType(STRING_TYPE); BindingImpl stringBinding = state.getExplicitBinding(stringKey); if (stringBinding == null || !stringBinding.isConstant()) { return null; } String stringValue = stringBinding.getProvider().get(); Object source = stringBinding.getSource(); // Find a matching type converter. TypeLiteral type = key.getTypeLiteral(); TypeConverterBinding typeConverterBinding = state.getConverter(stringValue, type, errors, source); if (typeConverterBinding == null) { // No converter can handle the given type. return null; } // Try to convert the string. A failed conversion results in an error. try { @SuppressWarnings("unchecked") // This cast is safe because we double check below. T converted = (T) typeConverterBinding.getTypeConverter().convert(stringValue, type); if (converted == null) { throw errors.converterReturnedNull(stringValue, source, type, typeConverterBinding) .toException(); } if (!type.getRawType().isInstance(converted)) { throw errors.conversionTypeError(stringValue, source, type, typeConverterBinding, converted) .toException(); } return new ConvertedConstantBindingImpl(this, key, converted, stringBinding, typeConverterBinding); } catch (ErrorsException e) { throw e; } catch (RuntimeException e) { throw errors.conversionError(stringValue, source, type, typeConverterBinding, e) .toException(); } } private static class ConvertedConstantBindingImpl extends BindingImpl implements ConvertedConstantBinding { final T value; final Provider provider; final Binding originalBinding; final TypeConverterBinding typeConverterBinding; ConvertedConstantBindingImpl( InjectorImpl injector, Key key, T value, Binding originalBinding, TypeConverterBinding typeConverterBinding) { super(injector, key, originalBinding.getSource(), new ConstantFactory(Initializables.of(value)), Scoping.UNSCOPED); this.value = value; provider = Providers.of(value); this.originalBinding = originalBinding; this.typeConverterBinding = typeConverterBinding; } @Override public Provider getProvider() { return provider; } public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } public T getValue() { return value; } public TypeConverterBinding getTypeConverterBinding() { return typeConverterBinding; } public Key getSourceKey() { return originalBinding.getKey(); } public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(getSourceKey())); } public void applyTo(Binder binder) { throw new UnsupportedOperationException("This element represents a synthetic binding."); } @Override public String toString() { return new ToStringBuilder(ConvertedConstantBinding.class) .add("key", getKey()) .add("sourceKey", getSourceKey()) .add("value", value) .toString(); } @Override public boolean equals(Object obj) { if(obj instanceof ConvertedConstantBindingImpl) { ConvertedConstantBindingImpl o = (ConvertedConstantBindingImpl)obj; return getKey().equals(o.getKey()) && getScoping().equals(o.getScoping()) && Objects.equal(value, o.value); } else { return false; } } @Override public int hashCode() { return Objects.hashCode(getKey(), getScoping(), value); } } void initializeBinding(BindingImpl binding, Errors errors) throws ErrorsException { if (binding instanceof ConstructorBindingImpl) { ((ConstructorBindingImpl) binding).initialize(this, errors); } } void initializeJitBinding(BindingImpl binding, Errors errors) throws ErrorsException { // Put the partially constructed binding in the map a little early. This enables us to handle // circular dependencies. Example: FooImpl -> BarImpl -> FooImpl. // Note: We don't need to synchronize on state.lock() during injector creation. if (binding instanceof ConstructorBindingImpl) { Key key = binding.getKey(); jitBindings.put(key, binding); boolean successful = false; ConstructorBindingImpl cb = (ConstructorBindingImpl)binding; try { cb.initialize(this, errors); successful = true; } finally { if (!successful) { // We do not pass cb.getInternalConstructor as the second parameter // so that cached exceptions while constructing it get stored. // See TypeListenerTest#testTypeListenerThrows removeFailedJitBinding(key, null); cleanup(binding, new HashSet()); } } } } /** * Iterates through the binding's dependencies to clean up any stray bindings that were leftover * from a failed JIT binding. This is required because the bindings are eagerly & * optimistically added to allow circular dependency support, so dependencies may pass where they * should have failed. */ private boolean cleanup(BindingImpl binding, Set encountered) { boolean bindingFailed = false; Set> deps = getInternalDependencies(binding); for(Dependency dep : deps) { Key depKey = dep.getKey(); InjectionPoint ip = dep.getInjectionPoint(); if(encountered.add(depKey)) { // only check if we haven't looked at this key yet BindingImpl depBinding = jitBindings.get(depKey); if(depBinding != null) { // if the binding still exists, validate boolean failed = cleanup(depBinding, encountered); // if children fail, we fail if(depBinding instanceof ConstructorBindingImpl) { ConstructorBindingImpl ctorBinding = (ConstructorBindingImpl)depBinding; ip = ctorBinding.getInternalConstructor(); if(!ctorBinding.isInitialized()) { failed = true; } } if(failed) { removeFailedJitBinding(depKey, ip); bindingFailed = true; } } else if(state.getExplicitBinding(depKey) == null) { // ignore keys if they were explicitly bound, but if neither JIT // nor explicit, it's also invalid & should let parent know. bindingFailed = true; } } } return bindingFailed; } /** Cleans up any state that may have been cached when constructing the JIT binding. */ private void removeFailedJitBinding(Key key, InjectionPoint ip) { jitBindings.remove(key); membersInjectorStore.remove(key.getTypeLiteral()); if(ip != null) { constructors.remove(ip); } } /** Safely gets the dependencies of possibly not initialized bindings. */ @SuppressWarnings("unchecked") private Set> getInternalDependencies(BindingImpl binding) { if(binding instanceof ConstructorBindingImpl) { return ((ConstructorBindingImpl)binding).getInternalDependencies(); } else if(binding instanceof HasDependencies) { return ((HasDependencies)binding).getDependencies(); } else { return ImmutableSet.of(); } } /** * Creates a binding for an injectable type with the given scope. Looks for a scope on the type if * none is specified. */ BindingImpl createUninitializedBinding(Key key, Scoping scoping, Object source, Errors errors, boolean jitBinding) throws ErrorsException { Class rawType = key.getTypeLiteral().getRawType(); // Don't try to inject arrays, or enums. if (rawType.isArray() || rawType.isEnum()) { throw errors.missingImplementation(key).toException(); } // Handle TypeLiteral by binding the inner type if (rawType == TypeLiteral.class) { @SuppressWarnings("unchecked") // we have to fudge the inner type as Object BindingImpl binding = (BindingImpl) createTypeLiteralBinding( (Key>) key, errors); return binding; } // Handle @ImplementedBy ImplementedBy implementedBy = rawType.getAnnotation(ImplementedBy.class); if (implementedBy != null) { Annotations.checkForMisplacedScopeAnnotations(rawType, source, errors); return createImplementedByBinding(key, scoping, implementedBy, errors); } // Handle @ProvidedBy. ProvidedBy providedBy = rawType.getAnnotation(ProvidedBy.class); if (providedBy != null) { Annotations.checkForMisplacedScopeAnnotations(rawType, source, errors); return createProvidedByBinding(key, scoping, providedBy, errors); } return ConstructorBindingImpl.create(this, key, null, source, scoping, errors, jitBinding && options.jitDisabled); } /** * Converts a binding for a {@code Key>} to the value {@code TypeLiteral}. It's * a bit awkward because we have to pull out the inner type in the type literal. */ private BindingImpl> createTypeLiteralBinding( Key> key, Errors errors) throws ErrorsException { Type typeLiteralType = key.getTypeLiteral().getType(); if (!(typeLiteralType instanceof ParameterizedType)) { throw errors.cannotInjectRawTypeLiteral().toException(); } ParameterizedType parameterizedType = (ParameterizedType) typeLiteralType; Type innerType = parameterizedType.getActualTypeArguments()[0]; // this is unforunate. We don't support building TypeLiterals for type variable like 'T'. If // this proves problematic, we can probably fix TypeLiteral to support type variables if (!(innerType instanceof Class) && !(innerType instanceof GenericArrayType) && !(innerType instanceof ParameterizedType)) { throw errors.cannotInjectTypeLiteralOf(innerType).toException(); } @SuppressWarnings("unchecked") // by definition, innerType == T, so this is safe TypeLiteral value = (TypeLiteral) TypeLiteral.get(innerType); InternalFactory> factory = new ConstantFactory>( Initializables.of(value)); return new InstanceBindingImpl>(this, key, SourceProvider.UNKNOWN_SOURCE, factory, ImmutableSet.of(), value); } /** Creates a binding for a type annotated with @ProvidedBy. */ BindingImpl createProvidedByBinding(Key key, Scoping scoping, ProvidedBy providedBy, Errors errors) throws ErrorsException { final Class rawType = key.getTypeLiteral().getRawType(); final Class> providerType = providedBy.value(); // Make sure it's not the same type. TODO: Can we check for deeper loops? if (providerType == rawType) { throw errors.recursiveProviderType().toException(); } // Assume the provider provides an appropriate type. We double check at runtime. @SuppressWarnings("unchecked") final Key> providerKey = (Key>) Key.get(providerType); final BindingImpl> providerBinding = getBindingOrThrow(providerKey, errors, JitLimitation.NEW_OR_EXISTING_JIT); InternalFactory internalFactory = new InternalFactory() { public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) throws ErrorsException { errors = errors.withSource(providerKey); Provider provider = providerBinding.getInternalFactory().get( errors, context, dependency, true); try { Object o = provider.get(); if (o != null && !rawType.isInstance(o)) { throw errors.subtypeNotProvided(providerType, rawType).toException(); } @SuppressWarnings("unchecked") // protected by isInstance() check above T t = (T) o; return t; } catch (RuntimeException e) { throw errors.errorInProvider(e).toException(); } } }; Object source = rawType; return new LinkedProviderBindingImpl( this, key, source, Scoping.scope(key, this, internalFactory, source, scoping), scoping, providerKey); } /** Creates a binding for a type annotated with @ImplementedBy. */ private BindingImpl createImplementedByBinding(Key key, Scoping scoping, ImplementedBy implementedBy, Errors errors) throws ErrorsException { Class rawType = key.getTypeLiteral().getRawType(); Class implementationType = implementedBy.value(); // Make sure it's not the same type. TODO: Can we check for deeper cycles? if (implementationType == rawType) { throw errors.recursiveImplementationType().toException(); } // Make sure implementationType extends type. if (!rawType.isAssignableFrom(implementationType)) { throw errors.notASubtype(implementationType, rawType).toException(); } @SuppressWarnings("unchecked") // After the preceding check, this cast is safe. Class subclass = (Class) implementationType; // Look up the target binding. final Key targetKey = Key.get(subclass); final BindingImpl targetBinding = getBindingOrThrow(targetKey, errors, JitLimitation.NEW_OR_EXISTING_JIT); InternalFactory internalFactory = new InternalFactory() { public T get(Errors errors, InternalContext context, Dependency dependency, boolean linked) throws ErrorsException { return targetBinding.getInternalFactory().get( errors.withSource(targetKey), context, dependency, true); } }; Object source = rawType; return new LinkedBindingImpl( this, key, source, Scoping.scope(key, this, internalFactory, source, scoping), scoping, targetKey); } /** * Attempts to create a just-in-time binding for {@code key} in the root injector, falling back to * other ancestor injectors until this injector is tried. */ private BindingImpl createJustInTimeBindingRecursive(Key key, Errors errors, boolean jitDisabled, JitLimitation jitType) throws ErrorsException { // ask the parent to create the JIT binding if (parent != null) { try { return parent.createJustInTimeBindingRecursive(key, new Errors(), jitDisabled, parent.options.jitDisabled ? JitLimitation.NO_JIT : jitType); } catch (ErrorsException ignored) { } } if (state.isBlacklisted(key)) { Set sources = state.getSourcesForBlacklistedKey(key); throw errors.childBindingAlreadySet(key, sources).toException(); } BindingImpl binding = createJustInTimeBinding(key, errors, jitDisabled, jitType); state.parent().blacklist(key, binding.getSource()); jitBindings.put(key, binding); return binding; } /** * Returns a new just-in-time binding created by resolving {@code key}. The strategies used to * create just-in-time bindings are: *
    *
  1. Internalizing Providers. If the requested binding is for {@code Provider}, we delegate * to the binding for {@code T}. *
  2. Converting constants. *
  3. ImplementedBy and ProvidedBy annotations. Only for unannotated keys. *
  4. The constructor of the raw type. Only for unannotated keys. *
* * @throws com.google.inject.internal.ErrorsException if the binding cannot be created. */ private BindingImpl createJustInTimeBinding(Key key, Errors errors, boolean jitDisabled, JitLimitation jitType) throws ErrorsException { int numErrorsBefore = errors.size(); if (state.isBlacklisted(key)) { Set sources = state.getSourcesForBlacklistedKey(key); throw errors.childBindingAlreadySet(key, sources).toException(); } // Handle cases where T is a Provider. if (isProvider(key)) { // These casts are safe. We know T extends Provider and that given Key>, // createProviderBinding() will return BindingImpl>. @SuppressWarnings("unchecked") BindingImpl binding = (BindingImpl) createProviderBinding((Key) key, errors); return binding; } // Handle cases where T is a MembersInjector if (isMembersInjector(key)) { // These casts are safe. T extends MembersInjector and that given Key>, // createMembersInjectorBinding() will return BindingImpl>. @SuppressWarnings("unchecked") BindingImpl binding = (BindingImpl) createMembersInjectorBinding((Key) key, errors); return binding; } // Try to convert a constant string binding to the requested type. BindingImpl convertedBinding = convertConstantStringBinding(key, errors); if (convertedBinding != null) { return convertedBinding; } if (!isTypeLiteral(key) && jitDisabled && jitType != JitLimitation.NEW_OR_EXISTING_JIT) { throw errors.jitDisabled(key).toException(); } // If the key has an annotation... if (key.getAnnotationType() != null) { // Look for a binding without annotation attributes or return null. if (key.hasAttributes()) { try { Errors ignored = new Errors(); return getBindingOrThrow(key.withoutAttributes(), ignored, JitLimitation.NO_JIT); } catch (ErrorsException ignored) { // throw with a more appropriate message below } } throw errors.missingImplementation(key).toException(); } Object source = key.getTypeLiteral().getRawType(); BindingImpl binding = createUninitializedBinding(key, Scoping.UNSCOPED, source, errors, true); errors.throwIfNewErrors(numErrorsBefore); initializeJitBinding(binding, errors); return binding; } InternalFactory getInternalFactory(Key key, Errors errors, JitLimitation jitType) throws ErrorsException { return getBindingOrThrow(key, errors, jitType).getInternalFactory(); } public Map, Binding> getBindings() { return state.getExplicitBindingsThisLevel(); } public Map, Binding> getAllBindings() { synchronized (state.lock()) { return new ImmutableMap.Builder, Binding>() .putAll(state.getExplicitBindingsThisLevel()) .putAll(jitBindings) .build(); } } public Map, Scope> getScopeBindings() { return ImmutableMap.copyOf(state.getScopes()); } public Set getTypeConverterBindings() { return ImmutableSet.copyOf(state.getConvertersThisLevel()); } private static class BindingsMultimap { final Map, List>> multimap = Maps.newHashMap(); void put(TypeLiteral type, Binding binding) { List> bindingsForType = multimap.get(type); if (bindingsForType == null) { bindingsForType = Lists.newArrayList(); multimap.put(type, bindingsForType); } bindingsForType.add(binding); } @SuppressWarnings("unchecked") // safe because we only put matching entries into the map List> getAll(TypeLiteral type) { List> bindings = multimap.get(type); return bindings != null ? Collections.>unmodifiableList((List) multimap.get(type)) : ImmutableList.>of(); } } /** * Returns parameter injectors, or {@code null} if there are no parameters. */ SingleParameterInjector[] getParametersInjectors( List> parameters, Errors errors) throws ErrorsException { if (parameters.isEmpty()) { return null; } int numErrorsBefore = errors.size(); SingleParameterInjector[] result = new SingleParameterInjector[parameters.size()]; int i = 0; for (Dependency parameter : parameters) { try { result[i++] = createParameterInjector(parameter, errors.withSource(parameter)); } catch (ErrorsException rethrownBelow) { // rethrown below } } errors.throwIfNewErrors(numErrorsBefore); return result; } SingleParameterInjector createParameterInjector(final Dependency dependency, final Errors errors) throws ErrorsException { InternalFactory factory = getInternalFactory(dependency.getKey(), errors, JitLimitation.NO_JIT); return new SingleParameterInjector(dependency, factory); } /** Invokes a method. */ interface MethodInvoker { Object invoke(Object target, Object... parameters) throws IllegalAccessException, InvocationTargetException; } /** Cached constructor injectors for each type */ final ConstructorInjectorStore constructors = new ConstructorInjectorStore(this); /** Cached field and method injectors for each type. */ MembersInjectorStore membersInjectorStore; @SuppressWarnings("unchecked") // the members injector type is consistent with instance's type public void injectMembers(Object instance) { MembersInjector membersInjector = getMembersInjector(instance.getClass()); membersInjector.injectMembers(instance); } public MembersInjector getMembersInjector(TypeLiteral typeLiteral) { Errors errors = new Errors(typeLiteral); try { return membersInjectorStore.get(typeLiteral, errors); } catch (ErrorsException e) { throw new ConfigurationException(errors.merge(e.getErrors()).getMessages()); } } public MembersInjector getMembersInjector(Class type) { return getMembersInjector(TypeLiteral.get(type)); } public Provider getProvider(Class type) { return getProvider(Key.get(type)); } Provider getProviderOrThrow(final Key key, Errors errors) throws ErrorsException { final InternalFactory factory = getInternalFactory(key, errors, JitLimitation.NO_JIT); final Dependency dependency = Dependency.get(key); return new Provider() { public T get() { final Errors errors = new Errors(dependency); try { T t = callInContext(new ContextualCallable() { public T call(InternalContext context) throws ErrorsException { Dependency previous = context.setDependency(dependency); try { return factory.get(errors, context, dependency, false); } finally { context.setDependency(previous); } } }); errors.throwIfNewErrors(0); return t; } catch (ErrorsException e) { throw new ProvisionException(errors.merge(e.getErrors()).getMessages()); } } @Override public String toString() { return factory.toString(); } }; } public Provider getProvider(final Key key) { Errors errors = new Errors(key); try { Provider result = getProviderOrThrow(key, errors); errors.throwIfNewErrors(0); return result; } catch (ErrorsException e) { throw new ConfigurationException(errors.merge(e.getErrors()).getMessages()); } } public T getInstance(Key key) { return getProvider(key).get(); } public T getInstance(Class type) { return getProvider(type).get(); } final ThreadLocal localContext; /** Looks up thread local context. Creates (and removes) a new context if necessary. */ T callInContext(ContextualCallable callable) throws ErrorsException { Object[] reference = localContext.get(); if (reference[0] == null) { reference[0] = new InternalContext(); try { return callable.call((InternalContext)reference[0]); } finally { // Only clear the context if this call created it. reference[0] = null; } } else { // Someone else will clean up this context. return callable.call((InternalContext)reference[0]); } } public String toString() { return new ToStringBuilder(Injector.class) .add("bindings", state.getExplicitBindingsThisLevel().values()) .toString(); } } guice-3.0/core/src/com/google/inject/internal/ProviderMethod.java0000644000175000017500000001035711502350636025012 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Exposed; import com.google.inject.Key; import com.google.inject.PrivateBinder; import com.google.inject.Provider; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Objects; import com.google.inject.internal.util.StackTraceElements; import com.google.inject.spi.Dependency; import com.google.inject.spi.ProviderWithDependencies; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.Set; /** * A provider that invokes a method and returns its result. * * @author jessewilson@google.com (Jesse Wilson) */ public class ProviderMethod implements ProviderWithDependencies { private final Key key; private final Class scopeAnnotation; private final Object instance; private final Method method; private final ImmutableSet> dependencies; private final List> parameterProviders; private final boolean exposed; /** * @param method the method to invoke. It's return type must be the same type as {@code key}. */ ProviderMethod(Key key, Method method, Object instance, ImmutableSet> dependencies, List> parameterProviders, Class scopeAnnotation) { this.key = key; this.scopeAnnotation = scopeAnnotation; this.instance = instance; this.dependencies = dependencies; this.method = method; this.parameterProviders = parameterProviders; this.exposed = method.isAnnotationPresent(Exposed.class); method.setAccessible(true); } public Key getKey() { return key; } public Method getMethod() { return method; } // exposed for GIN public Object getInstance() { return instance; } public void configure(Binder binder) { binder = binder.withSource(method); if (scopeAnnotation != null) { binder.bind(key).toProvider(this).in(scopeAnnotation); } else { binder.bind(key).toProvider(this); } if (exposed) { // the cast is safe 'cause the only binder we have implements PrivateBinder. If there's a // misplaced @Exposed, calling this will add an error to the binder's error queue ((PrivateBinder) binder).expose(key); } } public T get() { Object[] parameters = new Object[parameterProviders.size()]; for (int i = 0; i < parameters.length; i++) { parameters[i] = parameterProviders.get(i).get(); } try { // We know this cast is safe becase T is the method's return type. @SuppressWarnings({ "unchecked", "UnnecessaryLocalVariable" }) T result = (T) method.invoke(instance, parameters); return result; } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw Exceptions.throwCleanly(e); } } public Set> getDependencies() { return dependencies; } @Override public String toString() { return "@Provides " + StackTraceElements.forMember(method).toString(); } @Override public boolean equals(Object obj) { if (obj instanceof ProviderMethod) { ProviderMethod o = (ProviderMethod)obj; return method.equals(o.method) && instance.equals(o.instance); } else { return false; } } @Override public int hashCode() { // Avoid calling hashCode on 'instance', which is a user-object // that might not be expecting it. // (We need to call equals, so we do. But we can avoid hashCode.) return Objects.hashCode(method); } } guice-3.0/core/src/com/google/inject/internal/LinkedProviderBindingImpl.java0000644000175000017500000000655211460133000027102 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Objects; import com.google.inject.internal.util.ToStringBuilder; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.ProviderKeyBinding; import java.util.Set; final class LinkedProviderBindingImpl extends BindingImpl implements ProviderKeyBinding, HasDependencies { final Key> providerKey; public LinkedProviderBindingImpl(InjectorImpl injector, Key key, Object source, InternalFactory internalFactory, Scoping scoping, Key> providerKey) { super(injector, key, source, internalFactory, scoping); this.providerKey = providerKey; } LinkedProviderBindingImpl(Object source, Key key, Scoping scoping, Key> providerKey) { super(source, key, scoping); this.providerKey = providerKey; } public V acceptTargetVisitor(BindingTargetVisitor visitor) { return visitor.visit(this); } public Key> getProviderKey() { return providerKey; } public Set> getDependencies() { return ImmutableSet.>of(Dependency.get(providerKey)); } public BindingImpl withScoping(Scoping scoping) { return new LinkedProviderBindingImpl(getSource(), getKey(), scoping, providerKey); } public BindingImpl withKey(Key key) { return new LinkedProviderBindingImpl(getSource(), key, getScoping(), providerKey); } public void applyTo(Binder binder) { getScoping().applyTo(binder.withSource(getSource()) .bind(getKey()).toProvider(getProviderKey())); } @Override public String toString() { return new ToStringBuilder(ProviderKeyBinding.class) .add("key", getKey()) .add("source", getSource()) .add("scope", getScoping()) .add("provider", providerKey) .toString(); } @Override public boolean equals(Object obj) { if(obj instanceof LinkedProviderBindingImpl) { LinkedProviderBindingImpl o = (LinkedProviderBindingImpl)obj; return getKey().equals(o.getKey()) && getScoping().equals(o.getScoping()) && Objects.equal(providerKey, o.providerKey); } else { return false; } } @Override public int hashCode() { return Objects.hashCode(getKey(), getScoping(), providerKey); } } guice-3.0/core/src/com/google/inject/internal/ScopeBindingProcessor.java0000644000175000017500000000374011460133000026304 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.Scope; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.spi.ScopeBinding; import java.lang.annotation.Annotation; /** * Handles {@code Binder.bindScope} commands. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ final class ScopeBindingProcessor extends AbstractProcessor { ScopeBindingProcessor(Errors errors) { super(errors); } @Override public Boolean visit(ScopeBinding command) { Scope scope = command.getScope(); Class annotationType = command.getAnnotationType(); if (!Annotations.isScopeAnnotation(annotationType)) { errors.withSource(annotationType).missingScopeAnnotation(); // Go ahead and bind anyway so we don't get collateral errors. } if (!Annotations.isRetainedAtRuntime(annotationType)) { errors.withSource(annotationType) .missingRuntimeRetention(command.getSource()); // Go ahead and bind anyway so we don't get collateral errors. } Scope existing = injector.state.getScope(checkNotNull(annotationType, "annotation type")); if (existing != null) { errors.duplicateScopes(existing, annotationType, scope); } else { injector.state.putAnnotation(annotationType, checkNotNull(scope, "scope")); } return true; } }guice-3.0/core/src/com/google/inject/internal/SingleMethodInjector.java0000644000175000017500000000676711460133000026134 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.internal.BytecodeGen.Visibility; import com.google.inject.internal.InjectorImpl.MethodInvoker; import com.google.inject.spi.InjectionPoint; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; /** * Invokes an injectable method. */ final class SingleMethodInjector implements SingleMemberInjector { private final MethodInvoker methodInvoker; private final SingleParameterInjector[] parameterInjectors; private final InjectionPoint injectionPoint; SingleMethodInjector(InjectorImpl injector, InjectionPoint injectionPoint, Errors errors) throws ErrorsException { this.injectionPoint = injectionPoint; final Method method = (Method) injectionPoint.getMember(); methodInvoker = createMethodInvoker(method); parameterInjectors = injector.getParametersInjectors(injectionPoint.getDependencies(), errors); } private MethodInvoker createMethodInvoker(final Method method) { // We can't use FastMethod if the method is private. int modifiers = method.getModifiers(); if (!Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers)) { /*if[AOP]*/ try { final net.sf.cglib.reflect.FastMethod fastMethod = BytecodeGen.newFastClass(method.getDeclaringClass(), Visibility.forMember(method)) .getMethod(method); return new MethodInvoker() { public Object invoke(Object target, Object... parameters) throws IllegalAccessException, InvocationTargetException { return fastMethod.invoke(target, parameters); } }; } catch (net.sf.cglib.core.CodeGenerationException e) {/* fall-through */} /*end[AOP]*/ } if (!Modifier.isPublic(modifiers) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { method.setAccessible(true); } return new MethodInvoker() { public Object invoke(Object target, Object... parameters) throws IllegalAccessException, InvocationTargetException { return method.invoke(target, parameters); } }; } public InjectionPoint getInjectionPoint() { return injectionPoint; } public void inject(Errors errors, InternalContext context, Object o) { Object[] parameters; try { parameters = SingleParameterInjector.getAll(errors, context, parameterInjectors); } catch (ErrorsException e) { errors.merge(e.getErrors()); return; } try { methodInvoker.invoke(o, parameters); } catch (IllegalAccessException e) { throw new AssertionError(e); // a security manager is blocking us, we're hosed } catch (InvocationTargetException userException) { Throwable cause = userException.getCause() != null ? userException.getCause() : userException; errors.withSource(injectionPoint).errorInjectingMethod(cause); } } } guice-3.0/core/src/com/google/inject/internal/MoreTypes.java0000644000175000017500000004305411461640300024000 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.internal; import com.google.inject.ConfigurationException; import com.google.inject.TypeLiteral; import com.google.inject.internal.util.ImmutableMap; import com.google.inject.internal.util.Objects; import static com.google.inject.internal.util.Preconditions.checkArgument; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.util.Types; import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.GenericDeclaration; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.Arrays; import java.util.Map; import java.util.NoSuchElementException; /** * Static methods for working with types that we aren't publishing in the * public {@code Types} API. * * @author jessewilson@google.com (Jesse Wilson) */ public class MoreTypes { public static final Type[] EMPTY_TYPE_ARRAY = new Type[] {}; private MoreTypes() {} private static final Map, TypeLiteral> PRIMITIVE_TO_WRAPPER = new ImmutableMap.Builder, TypeLiteral>() .put(TypeLiteral.get(boolean.class), TypeLiteral.get(Boolean.class)) .put(TypeLiteral.get(byte.class), TypeLiteral.get(Byte.class)) .put(TypeLiteral.get(short.class), TypeLiteral.get(Short.class)) .put(TypeLiteral.get(int.class), TypeLiteral.get(Integer.class)) .put(TypeLiteral.get(long.class), TypeLiteral.get(Long.class)) .put(TypeLiteral.get(float.class), TypeLiteral.get(Float.class)) .put(TypeLiteral.get(double.class), TypeLiteral.get(Double.class)) .put(TypeLiteral.get(char.class), TypeLiteral.get(Character.class)) .put(TypeLiteral.get(void.class), TypeLiteral.get(Void.class)) .build(); /** * Returns an type that's appropriate for use in a key. * *

If the raw type of {@code typeLiteral} is a {@code javax.inject.Provider}, this returns a * {@code com.google.inject.Provider} with the same type parameters. * *

If the type is a primitive, the corresponding wrapper type will be returned. * * @throws ConfigurationException if {@code type} contains a type variable */ public static TypeLiteral canonicalizeForKey(TypeLiteral typeLiteral) { Type type = typeLiteral.getType(); if (!isFullySpecified(type)) { Errors errors = new Errors().keyNotFullySpecified(typeLiteral); throw new ConfigurationException(errors.getMessages()); } if (typeLiteral.getRawType() == javax.inject.Provider.class) { ParameterizedType parameterizedType = (ParameterizedType) type; // the following casts are generally unsafe, but com.google.inject.Provider extends // javax.inject.Provider and is covariant @SuppressWarnings("unchecked") TypeLiteral guiceProviderType = (TypeLiteral) TypeLiteral.get( Types.providerOf(parameterizedType.getActualTypeArguments()[0])); return guiceProviderType; } @SuppressWarnings("unchecked") TypeLiteral wrappedPrimitives = (TypeLiteral) PRIMITIVE_TO_WRAPPER.get(typeLiteral); return wrappedPrimitives != null ? wrappedPrimitives : typeLiteral; } /** * Returns true if {@code type} is free from type variables. */ private static boolean isFullySpecified(Type type) { if (type instanceof Class) { return true; } else if (type instanceof CompositeType) { return ((CompositeType) type).isFullySpecified(); } else if (type instanceof TypeVariable){ return false; } else { return ((CompositeType) canonicalize(type)).isFullySpecified(); } } /** * Returns a type that is functionally equal but not necessarily equal * according to {@link Object#equals(Object) Object.equals()}. The returned * type is {@link Serializable}. */ public static Type canonicalize(Type type) { if (type instanceof Class) { Class c = (Class) type; return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c; } else if (type instanceof CompositeType) { return type; } else if (type instanceof ParameterizedType) { ParameterizedType p = (ParameterizedType) type; return new ParameterizedTypeImpl(p.getOwnerType(), p.getRawType(), p.getActualTypeArguments()); } else if (type instanceof GenericArrayType) { GenericArrayType g = (GenericArrayType) type; return new GenericArrayTypeImpl(g.getGenericComponentType()); } else if (type instanceof WildcardType) { WildcardType w = (WildcardType) type; return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds()); } else { // type is either serializable as-is or unsupported return type; } } public static Class getRawType(Type type) { if (type instanceof Class) { // type is a normal class. return (Class) type; } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; // I'm not exactly sure why getRawType() returns Type instead of Class. // Neal isn't either but suspects some pathological case related // to nested classes exists. Type rawType = parameterizedType.getRawType(); checkArgument(rawType instanceof Class, "Expected a Class, but <%s> is of type %s", type, type.getClass().getName()); return (Class) rawType; } else if (type instanceof GenericArrayType) { Type componentType = ((GenericArrayType)type).getGenericComponentType(); return Array.newInstance(getRawType(componentType), 0).getClass(); } else if (type instanceof TypeVariable) { // we could use the variable's bounds, but that'll won't work if there are multiple. // having a raw type that's more general than necessary is okay return Object.class; } else { throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName()); } } /** * Returns true if {@code a} and {@code b} are equal. */ public static boolean equals(Type a, Type b) { if (a == b) { // also handles (a == null && b == null) return true; } else if (a instanceof Class) { // Class already specifies equals(). return a.equals(b); } else if (a instanceof ParameterizedType) { if (!(b instanceof ParameterizedType)) { return false; } // TODO: save a .clone() call ParameterizedType pa = (ParameterizedType) a; ParameterizedType pb = (ParameterizedType) b; return Objects.equal(pa.getOwnerType(), pb.getOwnerType()) && pa.getRawType().equals(pb.getRawType()) && Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments()); } else if (a instanceof GenericArrayType) { if (!(b instanceof GenericArrayType)) { return false; } GenericArrayType ga = (GenericArrayType) a; GenericArrayType gb = (GenericArrayType) b; return equals(ga.getGenericComponentType(), gb.getGenericComponentType()); } else if (a instanceof WildcardType) { if (!(b instanceof WildcardType)) { return false; } WildcardType wa = (WildcardType) a; WildcardType wb = (WildcardType) b; return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds()) && Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds()); } else if (a instanceof TypeVariable) { if (!(b instanceof TypeVariable)) { return false; } TypeVariable va = (TypeVariable) a; TypeVariable vb = (TypeVariable) b; return va.getGenericDeclaration() == vb.getGenericDeclaration() && va.getName().equals(vb.getName()); } else { // This isn't a type we support. Could be a generic array type, wildcard type, etc. return false; } } private static int hashCodeOrZero(Object o) { return o != null ? o.hashCode() : 0; } public static String typeToString(Type type) { return type instanceof Class ? ((Class) type).getName() : type.toString(); } /** * Returns the generic supertype for {@code supertype}. For example, given a class {@code * IntegerSet}, the result for when supertype is {@code Set.class} is {@code Set} and the * result when the supertype is {@code Collection.class} is {@code Collection}. */ public static Type getGenericSupertype(Type type, Class rawType, Class toResolve) { if (toResolve == rawType) { return type; } // we skip searching through interfaces if unknown is an interface if (toResolve.isInterface()) { Class[] interfaces = rawType.getInterfaces(); for (int i = 0, length = interfaces.length; i < length; i++) { if (interfaces[i] == toResolve) { return rawType.getGenericInterfaces()[i]; } else if (toResolve.isAssignableFrom(interfaces[i])) { return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve); } } } // check our supertypes if (!rawType.isInterface()) { while (rawType != Object.class) { Class rawSupertype = rawType.getSuperclass(); if (rawSupertype == toResolve) { return rawType.getGenericSuperclass(); } else if (toResolve.isAssignableFrom(rawSupertype)) { return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve); } rawType = rawSupertype; } } // we can't resolve this further return toResolve; } public static Type resolveTypeVariable(Type type, Class rawType, TypeVariable unknown) { Class declaredByRaw = declaringClassOf(unknown); // we can't reduce this further if (declaredByRaw == null) { return unknown; } Type declaredBy = getGenericSupertype(type, rawType, declaredByRaw); if (declaredBy instanceof ParameterizedType) { int index = indexOf(declaredByRaw.getTypeParameters(), unknown); return ((ParameterizedType) declaredBy).getActualTypeArguments()[index]; } return unknown; } private static int indexOf(Object[] array, Object toFind) { for (int i = 0; i < array.length; i++) { if (toFind.equals(array[i])) { return i; } } throw new NoSuchElementException(); } /** * Returns the declaring class of {@code typeVariable}, or {@code null} if it was not declared by * a class. */ private static Class declaringClassOf(TypeVariable typeVariable) { GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration(); return genericDeclaration instanceof Class ? (Class) genericDeclaration : null; } public static class ParameterizedTypeImpl implements ParameterizedType, Serializable, CompositeType { private final Type ownerType; private final Type rawType; private final Type[] typeArguments; public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) { // require an owner type if the raw type needs it if (rawType instanceof Class) { Class rawTypeAsClass = (Class) rawType; checkArgument(ownerType != null || rawTypeAsClass.getEnclosingClass() == null, "No owner type for enclosed %s", rawType); checkArgument(ownerType == null || rawTypeAsClass.getEnclosingClass() != null, "Owner type for unenclosed %s", rawType); } this.ownerType = ownerType == null ? null : canonicalize(ownerType); this.rawType = canonicalize(rawType); this.typeArguments = typeArguments.clone(); for (int t = 0; t < this.typeArguments.length; t++) { checkNotNull(this.typeArguments[t], "type parameter"); checkNotPrimitive(this.typeArguments[t], "type parameters"); this.typeArguments[t] = canonicalize(this.typeArguments[t]); } } public Type[] getActualTypeArguments() { return typeArguments.clone(); } public Type getRawType() { return rawType; } public Type getOwnerType() { return ownerType; } public boolean isFullySpecified() { if (ownerType != null && !MoreTypes.isFullySpecified(ownerType)) { return false; } if (!MoreTypes.isFullySpecified(rawType)) { return false; } for (Type type : typeArguments) { if (!MoreTypes.isFullySpecified(type)) { return false; } } return true; } @Override public boolean equals(Object other) { return other instanceof ParameterizedType && MoreTypes.equals(this, (ParameterizedType) other); } @Override public int hashCode() { return Arrays.hashCode(typeArguments) ^ rawType.hashCode() ^ hashCodeOrZero(ownerType); } @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(30 * (typeArguments.length + 1)); stringBuilder.append(typeToString(rawType)); if (typeArguments.length == 0) { return stringBuilder.toString(); } stringBuilder.append("<").append(typeToString(typeArguments[0])); for (int i = 1; i < typeArguments.length; i++) { stringBuilder.append(", ").append(typeToString(typeArguments[i])); } return stringBuilder.append(">").toString(); } private static final long serialVersionUID = 0; } public static class GenericArrayTypeImpl implements GenericArrayType, Serializable, CompositeType { private final Type componentType; public GenericArrayTypeImpl(Type componentType) { this.componentType = canonicalize(componentType); } public Type getGenericComponentType() { return componentType; } public boolean isFullySpecified() { return MoreTypes.isFullySpecified(componentType); } @Override public boolean equals(Object o) { return o instanceof GenericArrayType && MoreTypes.equals(this, (GenericArrayType) o); } @Override public int hashCode() { return componentType.hashCode(); } @Override public String toString() { return typeToString(componentType) + "[]"; } private static final long serialVersionUID = 0; } /** * The WildcardType interface supports multiple upper bounds and multiple * lower bounds. We only support what the Java 6 language needs - at most one * bound. If a lower bound is set, the upper bound must be Object.class. */ public static class WildcardTypeImpl implements WildcardType, Serializable, CompositeType { private final Type upperBound; private final Type lowerBound; public WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) { checkArgument(lowerBounds.length <= 1, "Must have at most one lower bound."); checkArgument(upperBounds.length == 1, "Must have exactly one upper bound."); if (lowerBounds.length == 1) { checkNotNull(lowerBounds[0], "lowerBound"); checkNotPrimitive(lowerBounds[0], "wildcard bounds"); checkArgument(upperBounds[0] == Object.class, "bounded both ways"); this.lowerBound = canonicalize(lowerBounds[0]); this.upperBound = Object.class; } else { checkNotNull(upperBounds[0], "upperBound"); checkNotPrimitive(upperBounds[0], "wildcard bounds"); this.lowerBound = null; this.upperBound = canonicalize(upperBounds[0]); } } public Type[] getUpperBounds() { return new Type[] { upperBound }; } public Type[] getLowerBounds() { return lowerBound != null ? new Type[] { lowerBound } : EMPTY_TYPE_ARRAY; } public boolean isFullySpecified() { return MoreTypes.isFullySpecified(upperBound) && (lowerBound == null || MoreTypes.isFullySpecified(lowerBound)); } @Override public boolean equals(Object other) { return other instanceof WildcardType && MoreTypes.equals(this, (WildcardType) other); } @Override public int hashCode() { // this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds()); return (lowerBound != null ? 31 + lowerBound.hashCode() : 1) ^ (31 + upperBound.hashCode()); } @Override public String toString() { if (lowerBound != null) { return "? super " + typeToString(lowerBound); } else if (upperBound == Object.class) { return "?"; } else { return "? extends " + typeToString(upperBound); } } private static final long serialVersionUID = 0; } private static void checkNotPrimitive(Type type, String use) { checkArgument(!(type instanceof Class) || !((Class) type).isPrimitive(), "Primitive types are not allowed in %s: %s", use, type); } /** A type formed from other types, such as arrays, parameterized types or wildcard types */ private interface CompositeType { /** Returns true if there are no type variables in this type. */ boolean isFullySpecified(); } } guice-3.0/core/src/com/google/inject/Stage.java0000644000175000017500000000245611460133000021272 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; /** * The stage we're running in. * * @author crazybob@google.com (Bob Lee) */ public enum Stage { /** * We're running in a tool (an IDE plugin for example). We need binding meta data but not a * functioning Injector. Do not inject members of instances. Do not load eager singletons. Do as * little as possible so our tools run nice and snappy. Injectors created in this stage cannot * be used to satisfy injections. */ TOOL, /** * We want fast startup times at the expense of runtime performance and some up front error * checking. */ DEVELOPMENT, /** * We want to catch errors as early as possible and take performance hits up front. */ PRODUCTION } guice-3.0/core/src/com/google/inject/ConfigurationException.java0000644000175000017500000000525511460133000024715 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.internal.Errors; import com.google.inject.internal.util.ImmutableSet; import static com.google.inject.internal.util.Preconditions.checkState; import com.google.inject.spi.Message; import java.util.Collection; /** * Thrown when a programming error such as a misplaced annotation, illegal binding, or unsupported * scope is found. Clients should catch this exception, log it, and stop execution. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class ConfigurationException extends RuntimeException { private final ImmutableSet messages; private Object partialValue = null; /** Creates a ConfigurationException containing {@code messages}. */ public ConfigurationException(Iterable messages) { this.messages = ImmutableSet.copyOf(messages); initCause(Errors.getOnlyCause(this.messages)); } /** Returns a copy of this configuration exception with the specified partial value. */ public ConfigurationException withPartialValue(Object partialValue) { checkState(this.partialValue == null, "Can't clobber existing partial value %s with %s", this.partialValue, partialValue); ConfigurationException result = new ConfigurationException(messages); result.partialValue = partialValue; return result; } /** Returns messages for the errors that caused this exception. */ public Collection getErrorMessages() { return messages; } /** * Returns a value that was only partially computed due to this exception. The caller can use * this while collecting additional configuration problems. * * @return the partial value, or {@code null} if none was set. The type of the partial value is * specified by the throwing method. */ @SuppressWarnings("unchecked") // this is *extremely* unsafe. We trust the caller here. public E getPartialValue() { return (E) partialValue; } @Override public String getMessage() { return Errors.format("Guice configuration errors", messages); } private static final long serialVersionUID = 0; }guice-3.0/core/src/com/google/inject/TypeLiteral.java0000644000175000017500000002704511473267710022512 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.internal.MoreTypes; import static com.google.inject.internal.MoreTypes.canonicalize; import com.google.inject.internal.util.ImmutableList; import static com.google.inject.internal.util.Preconditions.checkArgument; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.util.Types; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.List; /** * Represents a generic type {@code T}. Java doesn't yet provide a way to * represent generic types, so this class does. Forces clients to create a * subclass of this class which enables retrieval the type information even at * runtime. * *

For example, to create a type literal for {@code List}, you can * create an empty anonymous inner class: * *

* {@code TypeLiteral> list = new TypeLiteral>() {};} * *

Along with modeling generic types, this class can resolve type parameters. * For example, to figure out what type {@code keySet()} returns on a {@code * Map}, use this code:

   {@code
 *
 *   TypeLiteral> mapType
 *       = new TypeLiteral>() {};
 *   TypeLiteral keySetType
 *       = mapType.getReturnType(Map.class.getMethod("keySet"));
 *   System.out.println(keySetType); // prints "Set"}
* * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ public class TypeLiteral { final Class rawType; final Type type; final int hashCode; /** * Constructs a new type literal. Derives represented class from type * parameter. * *

Clients create an empty anonymous subclass. Doing so embeds the type * parameter in the anonymous class's type hierarchy so we can reconstitute it * at runtime despite erasure. */ @SuppressWarnings("unchecked") protected TypeLiteral() { this.type = getSuperclassTypeParameter(getClass()); this.rawType = (Class) MoreTypes.getRawType(type); this.hashCode = type.hashCode(); } /** * Unsafe. Constructs a type literal manually. */ @SuppressWarnings("unchecked") TypeLiteral(Type type) { this.type = canonicalize(checkNotNull(type, "type")); this.rawType = (Class) MoreTypes.getRawType(this.type); this.hashCode = this.type.hashCode(); } /** * Returns the type from super class's type parameter in {@link MoreTypes#canonicalize(Type) * canonical form}. */ static Type getSuperclassTypeParameter(Class subclass) { Type superclass = subclass.getGenericSuperclass(); if (superclass instanceof Class) { throw new RuntimeException("Missing type parameter."); } ParameterizedType parameterized = (ParameterizedType) superclass; return canonicalize(parameterized.getActualTypeArguments()[0]); } /** * Gets type literal from super class's type parameter. */ static TypeLiteral fromSuperclassTypeParameter(Class subclass) { return new TypeLiteral(getSuperclassTypeParameter(subclass)); } /** * Returns the raw (non-generic) type for this type. * * @since 2.0 */ public final Class getRawType() { return rawType; } /** * Gets underlying {@code Type} instance. */ public final Type getType() { return type; } /** * Gets the type of this type's provider. */ @SuppressWarnings("unchecked") final TypeLiteral> providerType() { // This cast is safe and wouldn't generate a warning if Type had a type // parameter. return (TypeLiteral>) get(Types.providerOf(getType())); } @Override public final int hashCode() { return this.hashCode; } @Override public final boolean equals(Object o) { return o instanceof TypeLiteral && MoreTypes.equals(type, ((TypeLiteral) o).type); } @Override public final String toString() { return MoreTypes.typeToString(type); } /** * Gets type literal for the given {@code Type} instance. */ public static TypeLiteral get(Type type) { return new TypeLiteral(type); } /** * Gets type literal for the given {@code Class} instance. */ public static TypeLiteral get(Class type) { return new TypeLiteral(type); } /** Returns an immutable list of the resolved types. */ private List> resolveAll(Type[] types) { TypeLiteral[] result = new TypeLiteral[types.length]; for (int t = 0; t < types.length; t++) { result[t] = resolve(types[t]); } return ImmutableList.of(result); } /** * Resolves known type parameters in {@code toResolve} and returns the result. */ TypeLiteral resolve(Type toResolve) { return TypeLiteral.get(resolveType(toResolve)); } Type resolveType(Type toResolve) { // this implementation is made a little more complicated in an attempt to avoid object-creation while (true) { if (toResolve instanceof TypeVariable) { TypeVariable original = (TypeVariable) toResolve; toResolve = MoreTypes.resolveTypeVariable(type, rawType, original); if (toResolve == original) { return toResolve; } } else if (toResolve instanceof GenericArrayType) { GenericArrayType original = (GenericArrayType) toResolve; Type componentType = original.getGenericComponentType(); Type newComponentType = resolveType(componentType); return componentType == newComponentType ? original : Types.arrayOf(newComponentType); } else if (toResolve instanceof ParameterizedType) { ParameterizedType original = (ParameterizedType) toResolve; Type ownerType = original.getOwnerType(); Type newOwnerType = resolveType(ownerType); boolean changed = newOwnerType != ownerType; Type[] args = original.getActualTypeArguments(); for (int t = 0, length = args.length; t < length; t++) { Type resolvedTypeArgument = resolveType(args[t]); if (resolvedTypeArgument != args[t]) { if (!changed) { args = args.clone(); changed = true; } args[t] = resolvedTypeArgument; } } return changed ? Types.newParameterizedTypeWithOwner(newOwnerType, original.getRawType(), args) : original; } else if (toResolve instanceof WildcardType) { WildcardType original = (WildcardType) toResolve; Type[] originalLowerBound = original.getLowerBounds(); Type[] originalUpperBound = original.getUpperBounds(); if (originalLowerBound.length == 1) { Type lowerBound = resolveType(originalLowerBound[0]); if (lowerBound != originalLowerBound[0]) { return Types.supertypeOf(lowerBound); } } else if (originalUpperBound.length == 1) { Type upperBound = resolveType(originalUpperBound[0]); if (upperBound != originalUpperBound[0]) { return Types.subtypeOf(upperBound); } } return original; } else { return toResolve; } } } /** * Returns the generic form of {@code supertype}. For example, if this is {@code * ArrayList}, this returns {@code Iterable} given the input {@code * Iterable.class}. * * @param supertype a superclass of, or interface implemented by, this. * @since 2.0 */ public TypeLiteral getSupertype(Class supertype) { checkArgument(supertype.isAssignableFrom(rawType), "%s is not a supertype of %s", supertype, this.type); return resolve(MoreTypes.getGenericSupertype(type, rawType, supertype)); } /** * Returns the resolved generic type of {@code field}. * * @param field a field defined by this or any superclass. * @since 2.0 */ public TypeLiteral getFieldType(Field field) { checkArgument(field.getDeclaringClass().isAssignableFrom(rawType), "%s is not defined by a supertype of %s", field, type); return resolve(field.getGenericType()); } /** * Returns the resolved generic parameter types of {@code methodOrConstructor}. * * @param methodOrConstructor a method or constructor defined by this or any supertype. * @since 2.0 */ public List> getParameterTypes(Member methodOrConstructor) { Type[] genericParameterTypes; if (methodOrConstructor instanceof Method) { Method method = (Method) methodOrConstructor; checkArgument(method.getDeclaringClass().isAssignableFrom(rawType), "%s is not defined by a supertype of %s", method, type); genericParameterTypes = method.getGenericParameterTypes(); } else if (methodOrConstructor instanceof Constructor) { Constructor constructor = (Constructor) methodOrConstructor; checkArgument(constructor.getDeclaringClass().isAssignableFrom(rawType), "%s does not construct a supertype of %s", constructor, type); genericParameterTypes = constructor.getGenericParameterTypes(); } else { throw new IllegalArgumentException("Not a method or a constructor: " + methodOrConstructor); } return resolveAll(genericParameterTypes); } /** * Returns the resolved generic exception types thrown by {@code constructor}. * * @param methodOrConstructor a method or constructor defined by this or any supertype. * @since 2.0 */ public List> getExceptionTypes(Member methodOrConstructor) { Type[] genericExceptionTypes; if (methodOrConstructor instanceof Method) { Method method = (Method) methodOrConstructor; checkArgument(method.getDeclaringClass().isAssignableFrom(rawType), "%s is not defined by a supertype of %s", method, type); genericExceptionTypes = method.getGenericExceptionTypes(); } else if (methodOrConstructor instanceof Constructor) { Constructor constructor = (Constructor) methodOrConstructor; checkArgument(constructor.getDeclaringClass().isAssignableFrom(rawType), "%s does not construct a supertype of %s", constructor, type); genericExceptionTypes = constructor.getGenericExceptionTypes(); } else { throw new IllegalArgumentException("Not a method or a constructor: " + methodOrConstructor); } return resolveAll(genericExceptionTypes); } /** * Returns the resolved generic return type of {@code method}. * * @param method a method defined by this or any supertype. * @since 2.0 */ public TypeLiteral getReturnType(Method method) { checkArgument(method.getDeclaringClass().isAssignableFrom(rawType), "%s is not defined by a supertype of %s", method, type); return resolve(method.getGenericReturnType()); } } guice-3.0/core/src/com/google/inject/Inject.java0000644000175000017500000000524511460133000021442 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Annotates members of your implementation class (constructors, methods * and fields) into which the {@link Injector} should inject values. * The Injector fulfills injection requests for: * *
    *
  • Every instance it constructs. The class being constructed must have * exactly one of its constructors marked with {@code @Inject} or must have a * constructor taking no parameters. The Injector then proceeds to perform * method and field injections. * *
  • Pre-constructed instances passed to {@link Injector#injectMembers}, * {@link com.google.inject.binder.LinkedBindingBuilder#toInstance(Object)} and * {@link com.google.inject.binder.LinkedBindingBuilder#toProvider(Provider)}. * In this case all constructors are, of course, ignored. * *
  • Static fields and methods of classes which any {@link Module} has * specifically requested static injection for, using * {@link Binder#requestStaticInjection}. *
* * In all cases, a member can be injected regardless of its Java access * specifier (private, default, protected, public). * * @author crazybob@google.com (Bob Lee) */ @Target({ METHOD, CONSTRUCTOR, FIELD }) @Retention(RUNTIME) @Documented public @interface Inject { /** * If true, and the appropriate binding is not found, * the Injector will skip injection of this method or field rather than * produce an error. When applied to a field, any default value already * assigned to the field will remain (guice will not actively null out the * field). When applied to a method, the method will only be invoked if * bindings for all parameters are found. When applied to a * constructor, an error will result upon Injector creation. */ boolean optional() default false; } guice-3.0/core/src/com/google/inject/binder/0000755000175000017500000000000011461101156020630 5ustar drazzibdrazzibguice-3.0/core/src/com/google/inject/binder/ConstantBindingBuilder.java0000644000175000017500000000310011463270234026066 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.binder; /** * Binds to a constant value. */ public interface ConstantBindingBuilder { /** * Binds constant to the given value. */ void to(String value); /** * Binds constant to the given value. */ void to(int value); /** * Binds constant to the given value. */ void to(long value); /** * Binds constant to the given value. */ void to(boolean value); /** * Binds constant to the given value. */ void to(double value); /** * Binds constant to the given value. */ void to(float value); /** * Binds constant to the given value. */ void to(short value); /** * Binds constant to the given value. */ void to(char value); /** * Binds constant to the given value. * * @since 3.0 */ void to(byte value); /** * Binds constant to the given value. */ void to(Class value); /** * Binds constant to the given value. */ > void to(E value); } guice-3.0/core/src/com/google/inject/binder/package-info.java0000644000175000017500000000132411460132772024026 0ustar drazzibdrazzib/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Interfaces which make up {@link com.google.inject.Binder}'s * expression language. */ package com.google.inject.binder;guice-3.0/core/src/com/google/inject/binder/AnnotatedElementBuilder.java0000644000175000017500000000213711460132772026243 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.binder; import java.lang.annotation.Annotation; /** * See the EDSL examples at {@link com.google.inject.Binder}. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface AnnotatedElementBuilder { /** * See the EDSL examples at {@link com.google.inject.Binder}. */ void annotatedWith(Class annotationType); /** * See the EDSL examples at {@link com.google.inject.Binder}. */ void annotatedWith(Annotation annotation); } guice-3.0/core/src/com/google/inject/binder/AnnotatedBindingBuilder.java0000644000175000017500000000223111460132772026217 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.binder; import java.lang.annotation.Annotation; /** * See the EDSL examples at {@link com.google.inject.Binder}. * * @author crazybob@google.com (Bob Lee) */ public interface AnnotatedBindingBuilder extends LinkedBindingBuilder { /** * See the EDSL examples at {@link com.google.inject.Binder}. */ LinkedBindingBuilder annotatedWith( Class annotationType); /** * See the EDSL examples at {@link com.google.inject.Binder}. */ LinkedBindingBuilder annotatedWith(Annotation annotation); } guice-3.0/core/src/com/google/inject/binder/LinkedBindingBuilder.java0000644000175000017500000000521011460132772025510 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.binder; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import java.lang.reflect.Constructor; /** * See the EDSL examples at {@link com.google.inject.Binder}. * * @author crazybob@google.com (Bob Lee) */ public interface LinkedBindingBuilder extends ScopedBindingBuilder { /** * See the EDSL examples at {@link com.google.inject.Binder}. */ ScopedBindingBuilder to(Class implementation); /** * See the EDSL examples at {@link com.google.inject.Binder}. */ ScopedBindingBuilder to(TypeLiteral implementation); /** * See the EDSL examples at {@link com.google.inject.Binder}. */ ScopedBindingBuilder to(Key targetKey); /** * See the EDSL examples at {@link com.google.inject.Binder}. * * @see com.google.inject.Injector#injectMembers */ void toInstance(T instance); /** * See the EDSL examples at {@link com.google.inject.Binder}. * * @see com.google.inject.Injector#injectMembers */ ScopedBindingBuilder toProvider(Provider provider); /** * See the EDSL examples at {@link com.google.inject.Binder}. */ ScopedBindingBuilder toProvider( Class> providerType); /** * See the EDSL examples at {@link com.google.inject.Binder}. */ ScopedBindingBuilder toProvider( TypeLiteral> providerType); /** * See the EDSL examples at {@link com.google.inject.Binder}. */ ScopedBindingBuilder toProvider( Key> providerKey); /** * See the EDSL examples at {@link com.google.inject.Binder}. * * @since 3.0 */ ScopedBindingBuilder toConstructor(Constructor constructor); /** * See the EDSL examples at {@link com.google.inject.Binder}. * * @since 3.0 */ ScopedBindingBuilder toConstructor( Constructor constructor, TypeLiteral type); } guice-3.0/core/src/com/google/inject/binder/ScopedBindingBuilder.java0000644000175000017500000000254011460132772025522 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.binder; import com.google.inject.Scope; import java.lang.annotation.Annotation; /** * See the EDSL examples at {@link com.google.inject.Binder}. * * @author crazybob@google.com (Bob Lee) */ public interface ScopedBindingBuilder { /** * See the EDSL examples at {@link com.google.inject.Binder}. */ void in(Class scopeAnnotation); /** * See the EDSL examples at {@link com.google.inject.Binder}. */ void in(Scope scope); /** * Instructs the {@link com.google.inject.Injector} to eagerly initialize this * singleton-scoped binding upon creation. Useful for application * initialization logic. See the EDSL examples at * {@link com.google.inject.Binder}. */ void asEagerSingleton(); } guice-3.0/core/src/com/google/inject/binder/AnnotatedConstantBindingBuilder.java0000644000175000017500000000217411460132772027737 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.binder; import java.lang.annotation.Annotation; /** * See the EDSL examples at {@link com.google.inject.Binder}. * * @author crazybob@google.com (Bob Lee) */ public interface AnnotatedConstantBindingBuilder { /** * See the EDSL examples at {@link com.google.inject.Binder}. */ ConstantBindingBuilder annotatedWith( Class annotationType); /** * See the EDSL examples at {@link com.google.inject.Binder}. */ ConstantBindingBuilder annotatedWith(Annotation annotation); } guice-3.0/core/src/com/google/inject/CreationException.java0000644000175000017500000000335611460133000023652 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.internal.Errors; import com.google.inject.internal.util.ImmutableSet; import static com.google.inject.internal.util.Preconditions.checkArgument; import com.google.inject.spi.Message; import java.util.Collection; /** * Thrown when errors occur while creating a {@link Injector}. Includes a list of encountered * errors. Clients should catch this exception, log it, and stop execution. * * @author crazybob@google.com (Bob Lee) */ public class CreationException extends RuntimeException { private final ImmutableSet messages; /** Creates a CreationException containing {@code messages}. */ public CreationException(Collection messages) { this.messages = ImmutableSet.copyOf(messages); checkArgument(!this.messages.isEmpty()); initCause(Errors.getOnlyCause(this.messages)); } /** Returns messages for the errors that caused this exception. */ public Collection getErrorMessages() { return messages; } @Override public String getMessage() { return Errors.format("Guice creation errors", messages); } private static final long serialVersionUID = 0; } guice-3.0/core/src/com/google/inject/Scope.java0000644000175000017500000000436411460133000021300 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; /** * A scope is a level of visibility that instances provided by Guice may have. * By default, an instance created by the {@link Injector} has no scope, * meaning it has no state from the framework's perspective -- the * {@code Injector} creates it, injects it once into the class that required it, * and then immediately forgets it. Associating a scope with a particular * binding allows the created instance to be "remembered" and possibly used * again for other injections. * *

An example of a scope is {@link Scopes#SINGLETON}. * * @author crazybob@google.com (Bob Lee) */ public interface Scope { /** * Scopes a provider. The returned provider returns objects from this scope. * If an object does not exist in this scope, the provider can use the given * unscoped provider to retrieve one. * *

Scope implementations are strongly encouraged to override * {@link Object#toString} in the returned provider and include the backing * provider's {@code toString()} output. * * @param key binding key * @param unscoped locates an instance when one doesn't already exist in this * scope. * @return a new provider which only delegates to the given unscoped provider * when an instance of the requested object doesn't already exist in this * scope */ public Provider scope(Key key, Provider unscoped); /** * A short but useful description of this scope. For comparison, the standard * scopes that ship with guice use the descriptions * {@code "Scopes.SINGLETON"}, {@code "ServletScopes.SESSION"} and * {@code "ServletScopes.REQUEST"}. */ String toString(); } guice-3.0/core/src/com/google/inject/Binder.java0000644000175000017500000004537611531414136021455 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.binder.AnnotatedConstantBindingBuilder; import com.google.inject.binder.LinkedBindingBuilder; import com.google.inject.matcher.Matcher; import com.google.inject.spi.Message; import com.google.inject.spi.TypeConverter; import com.google.inject.spi.TypeListener; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * Collects configuration information (primarily bindings) which will be * used to create an {@link Injector}. Guice provides this object to your * application's {@link Module} implementors so they may each contribute * their own bindings and other registrations. * *

The Guice Binding EDSL

* * Guice uses an embedded domain-specific language, or EDSL, to help you * create bindings simply and readably. This approach is great for overall * usability, but it does come with a small cost: it is difficult to * learn how to use the Binding EDSL by reading * method-level javadocs. Instead, you should consult the series of * examples below. To save space, these examples omit the opening * {@code binder}, just as you will if your module extends * {@link AbstractModule}. * *
 *     bind(ServiceImpl.class);
* * This statement does essentially nothing; it "binds the {@code ServiceImpl} * class to itself" and does not change Guice's default behavior. You may still * want to use this if you prefer your {@link Module} class to serve as an * explicit manifest for the services it provides. Also, in rare cases, * Guice may be unable to validate a binding at injector creation time unless it * is given explicitly. * *
 *     bind(Service.class).to(ServiceImpl.class);
* * Specifies that a request for a {@code Service} instance with no binding * annotations should be treated as if it were a request for a * {@code ServiceImpl} instance. This overrides the function of any * {@link ImplementedBy @ImplementedBy} or {@link ProvidedBy @ProvidedBy} * annotations found on {@code Service}, since Guice will have already * "moved on" to {@code ServiceImpl} before it reaches the point when it starts * looking for these annotations. * *
 *     bind(Service.class).toProvider(ServiceProvider.class);
* * In this example, {@code ServiceProvider} must extend or implement * {@code Provider}. This binding specifies that Guice should resolve * an unannotated injection request for {@code Service} by first resolving an * instance of {@code ServiceProvider} in the regular way, then calling * {@link Provider#get get()} on the resulting Provider instance to obtain the * {@code Service} instance. * *

The {@link Provider} you use here does not have to be a "factory"; that * is, a provider which always creates each instance it provides. * However, this is generally a good practice to follow. You can then use * Guice's concept of {@link Scope scopes} to guide when creation should happen * -- "letting Guice work for you". * *

 *     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);
* * Like the previous example, but only applies to injection requests that use * the binding annotation {@code @Red}. If your module also includes bindings * for particular values of the {@code @Red} annotation (see below), * then this binding will serve as a "catch-all" for any values of {@code @Red} * that have no exact match in the bindings. * *
 *     bind(ServiceImpl.class).in(Singleton.class);
 *     // or, alternatively
 *     bind(ServiceImpl.class).in(Scopes.SINGLETON);
* * Either of these statements places the {@code ServiceImpl} class into * singleton scope. Guice will create only one instance of {@code ServiceImpl} * and will reuse it for all injection requests of this type. Note that it is * still possible to bind another instance of {@code ServiceImpl} if the second * binding is qualified by an annotation as in the previous example. Guice is * not overly concerned with preventing you from creating multiple * instances of your "singletons", only with enabling your application to * share only one instance if that's all you tell Guice you need. * *

Note: a scope specified in this way overrides any scope that * was specified with an annotation on the {@code ServiceImpl} class. * *

Besides {@link Singleton}/{@link Scopes#SINGLETON}, there are * servlet-specific scopes available in * {@code com.google.inject.servlet.ServletScopes}, and your Modules can * contribute their own custom scopes for use here as well. * *

 *     bind(new TypeLiteral<PaymentService<CreditCard>>() {})
 *         .to(CreditCardPaymentService.class);
* * This admittedly odd construct is the way to bind a parameterized type. It * tells Guice how to honor an injection request for an element of type * {@code PaymentService}. The class * {@code CreditCardPaymentService} must implement the * {@code PaymentService} interface. Guice cannot currently bind or * inject a generic type, such as {@code Set}; all type parameters must be * fully specified. * *
 *     bind(Service.class).toInstance(new ServiceImpl());
 *     // or, alternatively
 *     bind(Service.class).toInstance(SomeLegacyRegistry.getService());
* * In this example, your module itself, not Guice, takes responsibility * for obtaining a {@code ServiceImpl} instance, then asks Guice to always use * this single instance to fulfill all {@code Service} injection requests. When * the {@link Injector} is created, it will automatically perform field * and method injection for this instance, but any injectable constructor on * {@code ServiceImpl} is simply ignored. Note that using this approach results * in "eager loading" behavior that you can't control. * *
 *     bindConstant().annotatedWith(ServerHost.class).to(args[0]);
* * Sets up a constant binding. Constant injections must always be annotated. * When a constant binding's value is a string, it is eligile for conversion to * all primitive types, to {@link Enum#valueOf(Class, String) all enums}, and to * {@link Class#forName class literals}. Conversions for other types can be * configured using {@link #convertToTypes(Matcher, TypeConverter) * convertToTypes()}. * *
 *   {@literal @}Color("red") Color red; // A member variable (field)
 *    . . .
 *     red = MyModule.class.getDeclaredField("red").getAnnotation(Color.class);
 *     bind(Service.class).annotatedWith(red).to(RedService.class);
* * If your binding annotation has parameters you can apply different bindings to * different specific values of your annotation. Getting your hands on the * right instance of the annotation is a bit of a pain -- one approach, shown * above, is to apply a prototype annotation to a field in your module class, so * that you can read this annotation instance and give it to Guice. * *
 *     bind(Service.class)
 *         .annotatedWith(Names.named("blue"))
 *         .to(BlueService.class);
* * Differentiating by names is a common enough use case that we provided a * standard annotation, {@link com.google.inject.name.Named @Named}. Because of * Guice's library support, binding by name is quite easier than in the * arbitrary binding annotation case we just saw. However, remember that these * names will live in a single flat namespace with all the other names used in * your application. * *
 *     Constructor loneCtor = getLoneCtorFromServiceImplViaReflection();
 *     bind(ServiceImpl.class)
 *         .toConstructor(loneCtor);
* * In this example, we directly tell Guice which constructor to use in a concrete * class implementation. It means that we do not need to place {@literal @}Inject * on any of the constructors and that Guice treats the provided constructor as though * it were annotated so. It is useful for cases where you cannot modify existing * classes and is a bit simpler than using a {@link Provider}. * *

The above list of examples is far from exhaustive. If you can think of * how the concepts of one example might coexist with the concepts from another, * you can most likely weave the two together. If the two concepts make no * sense with each other, you most likely won't be able to do it. In a few * cases Guice will let something bogus slip by, and will then inform you of * the problems at runtime, as soon as you try to create your Injector. * *

The other methods of Binder such as {@link #bindScope}, * {@link #bindInterceptor}, {@link #install}, {@link #requestStaticInjection}, * {@link #addError} and {@link #currentStage} are not part of the Binding EDSL; * you can learn how to use these in the usual way, from the method * documentation. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) * @author kevinb@google.com (Kevin Bourrillion) */ public interface Binder { /*if[AOP]*/ /** * Binds method interceptor[s] to methods matched by class and method matchers. A method is * eligible for interception if: * *

    *
  • Guice created the instance the method is on
  • *
  • Neither the enclosing type nor the method is final
  • *
  • And the method is package-private, protected, or public
  • *
* * @param classMatcher matches classes the interceptor should apply to. For * example: {@code only(Runnable.class)}. * @param methodMatcher matches methods the interceptor should apply to. For * example: {@code annotatedWith(Transactional.class)}. * @param interceptors to bind */ void bindInterceptor(Matcher> classMatcher, Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors); /*end[AOP]*/ /** * Binds a scope to an annotation. */ void bindScope(Class annotationType, Scope scope); /** * See the EDSL examples at {@link Binder}. */ LinkedBindingBuilder bind(Key key); /** * See the EDSL examples at {@link Binder}. */ AnnotatedBindingBuilder bind(TypeLiteral typeLiteral); /** * See the EDSL examples at {@link Binder}. */ AnnotatedBindingBuilder bind(Class type); /** * See the EDSL examples at {@link Binder}. */ AnnotatedConstantBindingBuilder bindConstant(); /** * Upon successful creation, the {@link Injector} will inject instance fields * and methods of the given object. * * @param type of instance * @param instance for which members will be injected * @since 2.0 */ void requestInjection(TypeLiteral type, T instance); /** * Upon successful creation, the {@link Injector} will inject instance fields * and methods of the given object. * * @param instance for which members will be injected * @since 2.0 */ void requestInjection(Object instance); /** * Upon successful creation, the {@link Injector} will inject static fields * and methods in the given classes. * * @param types for which static members will be injected */ void requestStaticInjection(Class... types); /** * Uses the given module to configure more bindings. */ void install(Module module); /** * Gets the current stage. */ Stage currentStage(); /** * Records an error message which will be presented to the user at a later * time. Unlike throwing an exception, this enable us to continue * configuring the Injector and discover more errors. Uses {@link * String#format(String, Object[])} to insert the arguments into the * message. */ void addError(String message, Object... arguments); /** * Records an exception, the full details of which will be logged, and the * message of which will be presented to the user at a later * time. If your Module calls something that you worry may fail, you should * catch the exception and pass it into this. */ void addError(Throwable t); /** * Records an error message to be presented to the user at a later time. * * @since 2.0 */ void addError(Message message); /** * Returns the provider used to obtain instances for the given injection key. * The returned provider will not be valid until the {@link Injector} has been * created. The provider will throw an {@code IllegalStateException} if you * try to use it beforehand. * * @since 2.0 */ Provider getProvider(Key key); /** * Returns the provider used to obtain instances for the given injection type. * The returned provider will not be valid until the {@link Injector} has been * created. The provider will throw an {@code IllegalStateException} if you * try to use it beforehand. * * @since 2.0 */ Provider getProvider(Class type); /** * Returns the members injector used to inject dependencies into methods and fields on instances * of the given type {@code T}. The returned members injector will not be valid until the main * {@link Injector} has been created. The members injector will throw an {@code * IllegalStateException} if you try to use it beforehand. * * @param typeLiteral type to get members injector for * @since 2.0 */ MembersInjector getMembersInjector(TypeLiteral typeLiteral); /** * Returns the members injector used to inject dependencies into methods and fields on instances * of the given type {@code T}. The returned members injector will not be valid until the main * {@link Injector} has been created. The members injector will throw an {@code * IllegalStateException} if you try to use it beforehand. * * @param type type to get members injector for * @since 2.0 */ MembersInjector getMembersInjector(Class type); /** * Binds a type converter. The injector will use the given converter to * convert string constants to matching types as needed. * * @param typeMatcher matches types the converter can handle * @param converter converts values * @since 2.0 */ void convertToTypes(Matcher> typeMatcher, TypeConverter converter); /** * Registers a listener for injectable types. Guice will notify the listener when it encounters * injectable types matched by the given type matcher. * * @param typeMatcher that matches injectable types the listener should be notified of * @param listener for injectable types matched by typeMatcher * @since 2.0 */ void bindListener(Matcher> typeMatcher, TypeListener listener); /** * Returns a binder that uses {@code source} as the reference location for * configuration errors. This is typically a {@link StackTraceElement} * for {@code .java} source but it could any binding source, such as the * path to a {@code .properties} file. * * @param source any object representing the source location and has a * concise {@link Object#toString() toString()} value * @return a binder that shares its configuration with this binder * @since 2.0 */ Binder withSource(Object source); /** * Returns a binder that skips {@code classesToSkip} when identify the * calling code. The caller's {@link StackTraceElement} is used to locate * the source of configuration errors. * * @param classesToSkip library classes that create bindings on behalf of * their clients. * @return a binder that shares its configuration with this binder. * @since 2.0 */ Binder skipSources(Class... classesToSkip); /** * Creates a new private child environment for bindings and other configuration. The returned * binder can be used to add and configuration information in this environment. See {@link * PrivateModule} for details. * * @return a binder that inherits configuration from this binder. Only exposed configuration on * the returned binder will be visible to this binder. * @since 2.0 */ PrivateBinder newPrivateBinder(); /** * Instructs the Injector that bindings must be listed in a Module in order to * be injected. Classes that are not explicitly bound in a module cannot be * injected. Bindings created through a linked binding ( * bind(Foo.class).to(FooImpl.class)) are allowed, but the * implicit binding (FooImpl) cannot be directly injected unless * it is also explicitly bound (bind(FooImpl.class)). *

* Tools can still retrieve bindings for implicit bindings (bindings created * through a linked binding) if explicit bindings are required, however * {@link Binding#getProvider} will fail. *

* By default, explicit bindings are not required. *

* If a parent injector requires explicit bindings, then all child injectors * (and private modules within that injector) also require explicit bindings. * If a parent does not require explicit bindings, a child injector or private * module may optionally declare itself as requiring explicit bindings. If it * does, the behavior is limited only to that child or any grandchildren. No * siblings of the child will require explicit bindings. *

* If the parent did not require explicit bindings but the child does, it is * possible that a linked binding in the child may add a JIT binding to the * parent. The child will not be allowed to reference the target binding * directly, but the parent and other children of the parent may be able to. * * @since 3.0 */ void requireExplicitBindings(); /** * Prevents Guice from constructing a {@link Proxy} when a circular dependency * is found. By default, circular proxies are not disabled. *

* If a parent injector disables circular proxies, then all child injectors * (and private modules within that injector) also disable circular proxies. * If a parent does not disable circular proxies, a child injector or private * module may optionally declare itself as disabling circular proxies. If it * does, the behavior is limited only to that child or any grandchildren. No * siblings of the child will disable circular proxies. * * @since 3.0 */ void disableCircularProxies(); } guice-3.0/core/src/com/google/inject/Injector.java0000644000175000017500000002544711530462750022030 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import java.lang.annotation.Annotation; import java.util.List; import java.util.Map; import java.util.Set; import com.google.inject.spi.TypeConverterBinding; /** * Builds the graphs of objects that make up your application. The injector tracks the dependencies * for each type and uses bindings to inject them. This is the core of Guice, although you rarely * interact with it directly. This "behind-the-scenes" operation is what distinguishes dependency * injection from its cousin, the service locator pattern. * *

Contains several default bindings: * *

    *
  • This {@link Injector} instance itself *
  • A {@code Provider} for each binding of type {@code T} *
  • The {@link java.util.logging.Logger} for the class being injected *
  • The {@link Stage} in which the Injector was created *
* * Injectors are created using the facade class {@link Guice}. * *

An injector can also {@link #injectMembers(Object) inject the dependencies} of * already-constructed instances. This can be used to interoperate with objects created by other * frameworks or services. * *

Injectors can be {@link #createChildInjector(Iterable) hierarchical}. Child injectors inherit * the configuration of their parent injectors, but the converse does not hold. * *

The injector's {@link #getBindings() internal bindings} are available for introspection. This * enables tools and extensions to operate on an injector reflectively. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ public interface Injector { /** * Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or * absence of an injectable constructor. * *

Whenever Guice creates an instance, it performs this injection automatically (after first * performing constructor injection), so if you're able to let Guice create all your objects for * you, you'll never need to use this method. * * @param instance to inject members on * * @see Binder#getMembersInjector(Class) for a preferred alternative that supports checks before * run time */ void injectMembers(Object instance); /** * Returns the members injector used to inject dependencies into methods and fields on instances * of the given type {@code T}. * * @param typeLiteral type to get members injector for * @see Binder#getMembersInjector(TypeLiteral) for an alternative that offers up front error * detection * @since 2.0 */ MembersInjector getMembersInjector(TypeLiteral typeLiteral); /** * Returns the members injector used to inject dependencies into methods and fields on instances * of the given type {@code T}. When feasible, use {@link Binder#getMembersInjector(TypeLiteral)} * instead to get increased up front error detection. * * @param type type to get members injector for * @see Binder#getMembersInjector(Class) for an alternative that offers up front error * detection * @since 2.0 */ MembersInjector getMembersInjector(Class type); /** * Returns this injector's explicit bindings. * *

The returned map does not include bindings inherited from a {@link #getParent() parent * injector}, should one exist. The returned map is guaranteed to iterate (for example, with * its {@link Map#entrySet()} iterator) in the order of insertion. In other words, the order in * which bindings appear in user Modules. * *

This method is part of the Guice SPI and is intended for use by tools and extensions. */ Map, Binding> getBindings(); /** * Returns a snapshot of this injector's bindings, both explicit and * just-in-time. The returned map is immutable; it contains only the bindings that were * present when {@code getAllBindings()} was invoked. Subsequent calls may return a map with * additional just-in-time bindings. * *

The returned map does not include bindings inherited from a {@link #getParent() parent * injector}, should one exist. * *

This method is part of the Guice SPI and is intended for use by tools and extensions. * * @since 3.0 */ Map, Binding> getAllBindings(); /** * Returns the binding for the given injection key. This will be an explicit bindings if the key * was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will * be created if necessary. * *

This method is part of the Guice SPI and is intended for use by tools and extensions. * * @throws ConfigurationException if this injector cannot find or create the binding. */ Binding getBinding(Key key); /** * Returns the binding for the given type. This will be an explicit bindings if the injection key * was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will * be created if necessary. * *

This method is part of the Guice SPI and is intended for use by tools and extensions. * * @throws ConfigurationException if this injector cannot find or create the binding. * @since 2.0 */ Binding getBinding(Class type); /** * Returns the binding if it already exists, or null if does not exist. Unlike * {@link #getBinding(Key)}, this does not attempt to create just-in-time bindings * for keys that aren't bound. * *

This method is part of the Guice SPI and is intended for use by tools and extensions. * * @since 3.0 */ Binding getExistingBinding(Key key); /** * Returns all explicit bindings for {@code type}. * *

This method is part of the Guice SPI and is intended for use by tools and extensions. */ List> findBindingsByType(TypeLiteral type); /** * Returns the provider used to obtain instances for the given injection key. When feasible, avoid * using this method, in favor of having Guice inject your dependencies ahead of time. * * @throws ConfigurationException if this injector cannot find or create the provider. * @see Binder#getProvider(Key) for an alternative that offers up front error detection */ Provider getProvider(Key key); /** * Returns the provider used to obtain instances for the given type. When feasible, avoid * using this method, in favor of having Guice inject your dependencies ahead of time. * * @throws ConfigurationException if this injector cannot find or create the provider. * @see Binder#getProvider(Class) for an alternative that offers up front error detection */ Provider getProvider(Class type); /** * Returns the appropriate instance for the given injection key; equivalent to {@code * getProvider(key).get()}. When feasible, avoid using this method, in favor of having Guice * inject your dependencies ahead of time. * * @throws ConfigurationException if this injector cannot find or create the provider. * @throws ProvisionException if there was a runtime failure while providing an instance. */ T getInstance(Key key); /** * Returns the appropriate instance for the given injection type; equivalent to {@code * getProvider(type).get()}. When feasible, avoid using this method, in favor of having Guice * inject your dependencies ahead of time. * * @throws ConfigurationException if this injector cannot find or create the provider. * @throws ProvisionException if there was a runtime failure while providing an instance. */ T getInstance(Class type); /** * Returns this injector's parent, or {@code null} if this is a top-level injector. * * @since 2.0 */ Injector getParent(); /** * Returns a new injector that inherits all state from this injector. All bindings, scopes, * interceptors and type converters are inherited -- they are visible to the child injector. * Elements of the child injector are not visible to its parent. * *

Just-in-time bindings created for child injectors will be created in an ancestor injector * whenever possible. This allows for scoped instances to be shared between injectors. Use * explicit bindings to prevent bindings from being shared with the parent injector. Optional * injections in just-in-time bindings (created in the parent injector) may be silently * ignored if the optional dependencies are from the child injector. * *

No key may be bound by both an injector and one of its ancestors. This includes just-in-time * bindings. The lone exception is the key for {@code Injector.class}, which is bound by each * injector to itself. * * @since 2.0 */ Injector createChildInjector(Iterable modules); /** * Returns a new injector that inherits all state from this injector. All bindings, scopes, * interceptors and type converters are inherited -- they are visible to the child injector. * Elements of the child injector are not visible to its parent. * *

Just-in-time bindings created for child injectors will be created in an ancestor injector * whenever possible. This allows for scoped instances to be shared between injectors. Use * explicit bindings to prevent bindings from being shared with the parent injector. * *

No key may be bound by both an injector and one of its ancestors. This includes just-in-time * bindings. The lone exception is the key for {@code Injector.class}, which is bound by each * injector to itself. * * @since 2.0 */ Injector createChildInjector(Module... modules); /** * Returns a map containing all scopes in the injector. The maps keys are scoping annotations * like {@code Singleton.class}, and the values are scope instances, such as {@code * Scopes.SINGLETON}. The returned map is immutable. * *

This method is part of the Guice SPI and is intended for use by tools and extensions. * * @since 3.0 */ Map, Scope> getScopeBindings(); /** * Returns a set containing all type converter bindings in the injector. The returned set is * immutable. * *

This method is part of the Guice SPI and is intended for use by tools and extensions. * * @since 3.0 */ Set getTypeConverterBindings(); } guice-3.0/core/src/com/google/inject/ProvisionException.java0000644000175000017500000000405611523504226024110 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.internal.Errors; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import static com.google.inject.internal.util.Preconditions.checkArgument; import com.google.inject.spi.Message; import java.util.Collection; /** * Indicates that there was a runtime failure while providing an instance. * * @author kevinb@google.com (Kevin Bourrillion) * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class ProvisionException extends RuntimeException { private final ImmutableSet messages; /** Creates a ProvisionException containing {@code messages}. */ public ProvisionException(Iterable messages) { this.messages = ImmutableSet.copyOf(messages); checkArgument(!this.messages.isEmpty()); initCause(Errors.getOnlyCause(this.messages)); } public ProvisionException(String message, Throwable cause) { super(cause); this.messages = ImmutableSet.of(new Message(ImmutableList.of(), message, cause)); } public ProvisionException(String message) { this.messages = ImmutableSet.of(new Message(message)); } /** Returns messages for the errors that caused this exception. */ public Collection getErrorMessages() { return messages; } @Override public String getMessage() { return Errors.format("Guice provision errors", messages); } private static final long serialVersionUID = 0; } guice-3.0/core/src/com/google/inject/Scopes.java0000644000175000017500000001355711461076654021515 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.internal.CircularDependencyProxy; import com.google.inject.internal.InternalInjectorCreator; import com.google.inject.internal.LinkedBindingImpl; import com.google.inject.spi.BindingScopingVisitor; import com.google.inject.spi.ExposedBinding; import java.lang.annotation.Annotation; /** * Built-in scope implementations. * * @author crazybob@google.com (Bob Lee) */ public class Scopes { private Scopes() {} /** A sentinel value representing null. */ private static final Object NULL = new Object(); /** * One instance per {@link Injector}. Also see {@code @}{@link Singleton}. */ public static final Scope SINGLETON = new Scope() { public Provider scope(final Key key, final Provider creator) { return new Provider() { /* * The lazily initialized singleton instance. Once set, this will either have type T or will * be equal to NULL. */ private volatile Object instance; // DCL on a volatile is safe as of Java 5, which we obviously require. @SuppressWarnings("DoubleCheckedLocking") public T get() { if (instance == null) { /* * Use a pretty coarse lock. We don't want to run into deadlocks * when two threads try to load circularly-dependent objects. * Maybe one of these days we will identify independent graphs of * objects and offer to load them in parallel. * * This block is re-entrant for circular dependencies. */ synchronized (InternalInjectorCreator.class) { if (instance == null) { T provided = creator.get(); // don't remember proxies; these exist only to serve circular dependencies if (provided instanceof CircularDependencyProxy) { return provided; } Object providedOrSentinel = (provided == null) ? NULL : provided; if (instance != null && instance != providedOrSentinel) { throw new ProvisionException( "Provider was reentrant while creating a singleton"); } instance = providedOrSentinel; } } } Object localInstance = instance; // This is safe because instance has type T or is equal to NULL @SuppressWarnings("unchecked") T returnedInstance = (localInstance != NULL) ? (T) localInstance : null; return returnedInstance; } public String toString() { return String.format("%s[%s]", creator, SINGLETON); } }; } @Override public String toString() { return "Scopes.SINGLETON"; } }; /** * No scope; the same as not applying any scope at all. Each time the * Injector obtains an instance of an object with "no scope", it injects this * instance then immediately forgets it. When the next request for the same * binding arrives it will need to obtain the instance over again. * *

This exists only in case a class has been annotated with a scope * annotation such as {@link Singleton @Singleton}, and you need to override * this to "no scope" in your binding. * * @since 2.0 */ public static final Scope NO_SCOPE = new Scope() { public Provider scope(Key key, Provider unscoped) { return unscoped; } @Override public String toString() { return "Scopes.NO_SCOPE"; } }; /** * Returns true if {@code binding} is singleton-scoped. If the binding is a {@link * com.google.inject.spi.LinkedKeyBinding linked key binding} and belongs to an injector (ie. it * was retrieved via {@link Injector#getBinding Injector.getBinding()}), then this method will * also true if the target binding is singleton-scoped. * * @since 3.0 */ public static boolean isSingleton(Binding binding) { do { boolean singleton = binding.acceptScopingVisitor(new BindingScopingVisitor() { public Boolean visitNoScoping() { return false; } public Boolean visitScopeAnnotation(Class scopeAnnotation) { return scopeAnnotation == Singleton.class || scopeAnnotation == javax.inject.Singleton.class; } public Boolean visitScope(Scope scope) { return scope == Scopes.SINGLETON; } public Boolean visitEagerSingleton() { return true; } }); if (singleton) { return true; } if (binding instanceof LinkedBindingImpl) { LinkedBindingImpl linkedBinding = (LinkedBindingImpl) binding; Injector injector = (Injector) linkedBinding.getInjector(); if (injector != null) { binding = injector.getBinding(linkedBinding.getLinkedKey()); continue; } } else if(binding instanceof ExposedBinding) { ExposedBinding exposedBinding = (ExposedBinding)binding; Injector injector = exposedBinding.getPrivateElements().getInjector(); if (injector != null) { binding = injector.getBinding(exposedBinding.getKey()); continue; } } return false; } while (true); } } guice-3.0/core/src/com/google/inject/Singleton.java0000644000175000017500000000214011460133000022157 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Apply this to implementation classes when you want only one instance * (per {@link Injector}) to be reused for all injections for that binding. * * @author crazybob@google.com (Bob Lee) */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RUNTIME) @ScopeAnnotation public @interface Singleton {} guice-3.0/core/src/com/google/inject/Binding.java0000644000175000017500000000713311460133000021576 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.spi.BindingScopingVisitor; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Element; /** * A mapping from a key (type and optional annotation) to the strategy for getting instances of the * type. This interface is part of the introspection API and is intended primarily for use by * tools. * *

Bindings are created in several ways: *

    *
  • Explicitly in a module, via {@code bind()} and {@code bindConstant()} * statements: *
     *     bind(Service.class).annotatedWith(Red.class).to(ServiceImpl.class);
     *     bindConstant().annotatedWith(ServerHost.class).to(args[0]);
  • *
  • Implicitly by the Injector by following a type's {@link ImplementedBy * pointer} {@link ProvidedBy annotations} or by using its {@link Inject annotated} or * default constructor.
  • *
  • By converting a bound instance to a different type.
  • *
  • For {@link Provider providers}, by delegating to the binding for the provided type.
  • *
* * *

They exist on both modules and on injectors, and their behaviour is different for each: *

    *
  • Module bindings are incomplete and cannot be used to provide instances. * This is because the applicable scopes and interceptors may not be known until an injector * is created. From a tool's perspective, module bindings are like the injector's source * code. They can be inspected or rewritten, but this analysis must be done statically.
  • *
  • Injector bindings are complete and valid and can be used to provide * instances. From a tools' perspective, injector bindings are like reflection for an * injector. They have full runtime information, including the complete graph of injections * necessary to satisfy a binding.
  • *
* * @param the bound type. The injected is always assignable to this type. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) */ public interface Binding extends Element { /** * Returns the key for this binding. */ Key getKey(); /** * Returns the scoped provider guice uses to fulfill requests for this * binding. * * @throws UnsupportedOperationException when invoked on a {@link Binding} * created via {@link com.google.inject.spi.Elements#getElements}. This * method is only supported on {@link Binding}s returned from an injector. */ Provider getProvider(); /** * Accepts a target visitor. Invokes the visitor method specific to this binding's target. * * @param visitor to call back on * @since 2.0 */ V acceptTargetVisitor(BindingTargetVisitor visitor); /** * Accepts a scoping visitor. Invokes the visitor method specific to this binding's scoping. * * @param visitor to call back on * @since 2.0 */ V acceptScopingVisitor(BindingScopingVisitor visitor); } guice-3.0/core/src/com/google/inject/Module.java0000644000175000017500000000320011460133000021440 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; /** * A module contributes configuration information, typically interface * bindings, which will be used to create an {@link Injector}. A Guice-based * application is ultimately composed of little more than a set of * {@code Module}s and some bootstrapping code. * *

Your Module classes can use a more streamlined syntax by extending * {@link AbstractModule} rather than implementing this interface directly. * *

In addition to the bindings configured via {@link #configure}, bindings * will be created for all methods annotated with {@literal @}{@link Provides}. * Use scope and binding annotations on these methods to configure the * bindings. */ public interface Module { /** * Contributes bindings and other configurations for this module to {@code binder}. * *

Do not invoke this method directly to install submodules. Instead use * {@link Binder#install(Module)}, which ensures that {@link Provides provider methods} are * discovered. */ void configure(Binder binder); } guice-3.0/core/src/com/google/inject/Provides.java0000644000175000017500000000225511460133000022017 0ustar drazzibdrazzib/** * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Annotates methods of a {@link Module} to create a provider method binding. The method's return * type is bound to it's returned value. Guice will pass dependencies to the method as parameters. * * @author crazybob@google.com (Bob Lee) * @since 2.0 */ @Documented @Target(METHOD) @Retention(RUNTIME) public @interface Provides {} guice-3.0/core/src/com/google/inject/Key.java0000644000175000017500000003317211460133000020756 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.internal.Annotations; import com.google.inject.internal.MoreTypes; import static com.google.inject.internal.util.Preconditions.checkArgument; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.lang.annotation.Annotation; import java.lang.reflect.Type; /** * Binding key consisting of an injection type and an optional annotation. * Matches the type and annotation at a point of injection. * *

For example, {@code Key.get(Service.class, Transactional.class)} will * match: * *

 *   {@literal @}Inject
 *   public void setService({@literal @}Transactional Service service) {
 *     ...
 *   }
 * 
* *

{@code Key} supports generic types via subclassing just like {@link * TypeLiteral}. * *

Keys do not differentiate between primitive types (int, char, etc.) and * their correpsonding wrapper types (Integer, Character, etc.). Primitive * types will be replaced with their wrapper types when keys are created. * * @author crazybob@google.com (Bob Lee) */ public class Key { private final AnnotationStrategy annotationStrategy; private final TypeLiteral typeLiteral; private final int hashCode; /** * Constructs a new key. Derives the type from this class's type parameter. * *

Clients create an empty anonymous subclass. Doing so embeds the type * parameter in the anonymous class's type hierarchy so we can reconstitute it * at runtime despite erasure. * *

Example usage for a binding of type {@code Foo} annotated with * {@code @Bar}: * *

{@code new Key(Bar.class) {}}. */ @SuppressWarnings("unchecked") protected Key(Class annotationType) { this.annotationStrategy = strategyFor(annotationType); this.typeLiteral = (TypeLiteral) TypeLiteral.fromSuperclassTypeParameter(getClass()); this.hashCode = computeHashCode(); } /** * Constructs a new key. Derives the type from this class's type parameter. * *

Clients create an empty anonymous subclass. Doing so embeds the type * parameter in the anonymous class's type hierarchy so we can reconstitute it * at runtime despite erasure. * *

Example usage for a binding of type {@code Foo} annotated with * {@code @Bar}: * *

{@code new Key(new Bar()) {}}. */ @SuppressWarnings("unchecked") protected Key(Annotation annotation) { // no usages, not test-covered this.annotationStrategy = strategyFor(annotation); this.typeLiteral = (TypeLiteral) TypeLiteral.fromSuperclassTypeParameter(getClass()); this.hashCode = computeHashCode(); } /** * Constructs a new key. Derives the type from this class's type parameter. * *

Clients create an empty anonymous subclass. Doing so embeds the type * parameter in the anonymous class's type hierarchy so we can reconstitute it * at runtime despite erasure. * *

Example usage for a binding of type {@code Foo}: * *

{@code new Key() {}}. */ @SuppressWarnings("unchecked") protected Key() { this.annotationStrategy = NullAnnotationStrategy.INSTANCE; this.typeLiteral = (TypeLiteral) TypeLiteral.fromSuperclassTypeParameter(getClass()); this.hashCode = computeHashCode(); } /** * Unsafe. Constructs a key from a manually specified type. */ @SuppressWarnings("unchecked") private Key(Type type, AnnotationStrategy annotationStrategy) { this.annotationStrategy = annotationStrategy; this.typeLiteral = MoreTypes.canonicalizeForKey((TypeLiteral) TypeLiteral.get(type)); this.hashCode = computeHashCode(); } /** Constructs a key from a manually specified type. */ private Key(TypeLiteral typeLiteral, AnnotationStrategy annotationStrategy) { this.annotationStrategy = annotationStrategy; this.typeLiteral = MoreTypes.canonicalizeForKey(typeLiteral); this.hashCode = computeHashCode(); } private int computeHashCode() { return typeLiteral.hashCode() * 31 + annotationStrategy.hashCode(); } /** * Gets the key type. */ public final TypeLiteral getTypeLiteral() { return typeLiteral; } /** * Gets the annotation type. */ public final Class getAnnotationType() { return annotationStrategy.getAnnotationType(); } /** * Gets the annotation. */ public final Annotation getAnnotation() { return annotationStrategy.getAnnotation(); } boolean hasAnnotationType() { return annotationStrategy.getAnnotationType() != null; } String getAnnotationName() { Annotation annotation = annotationStrategy.getAnnotation(); if (annotation != null) { return annotation.toString(); } // not test-covered return annotationStrategy.getAnnotationType().toString(); } Class getRawType() { return typeLiteral.getRawType(); } /** * Gets the key of this key's provider. */ Key> providerKey() { return ofType(typeLiteral.providerType()); } @Override public final boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof Key)) { return false; } Key other = (Key) o; return annotationStrategy.equals(other.annotationStrategy) && typeLiteral.equals(other.typeLiteral); } @Override public final int hashCode() { return this.hashCode; } @Override public final String toString() { return "Key[type=" + typeLiteral + ", annotation=" + annotationStrategy + "]"; } /** * Gets a key for an injection type and an annotation strategy. */ static Key get(Class type, AnnotationStrategy annotationStrategy) { return new Key(type, annotationStrategy); } /** * Gets a key for an injection type. */ public static Key get(Class type) { return new Key(type, NullAnnotationStrategy.INSTANCE); } /** * Gets a key for an injection type and an annotation type. */ public static Key get(Class type, Class annotationType) { return new Key(type, strategyFor(annotationType)); } /** * Gets a key for an injection type and an annotation. */ public static Key get(Class type, Annotation annotation) { return new Key(type, strategyFor(annotation)); } /** * Gets a key for an injection type. */ public static Key get(Type type) { return new Key(type, NullAnnotationStrategy.INSTANCE); } /** * Gets a key for an injection type and an annotation type. */ public static Key get(Type type, Class annotationType) { return new Key(type, strategyFor(annotationType)); } /** * Gets a key for an injection type and an annotation. */ public static Key get(Type type, Annotation annotation) { return new Key(type, strategyFor(annotation)); } /** * Gets a key for an injection type. */ public static Key get(TypeLiteral typeLiteral) { return new Key(typeLiteral, NullAnnotationStrategy.INSTANCE); } /** * Gets a key for an injection type and an annotation type. */ public static Key get(TypeLiteral typeLiteral, Class annotationType) { return new Key(typeLiteral, strategyFor(annotationType)); } /** * Gets a key for an injection type and an annotation. */ public static Key get(TypeLiteral typeLiteral, Annotation annotation) { return new Key(typeLiteral, strategyFor(annotation)); } /** * Returns a new key of the specified type with the same annotation as this * key. * * @since 3.0 */ public Key ofType(Class type) { return new Key(type, annotationStrategy); } /** * Returns a new key of the specified type with the same annotation as this * key. * * @since 3.0 */ public Key ofType(Type type) { return new Key(type, annotationStrategy); } /** * Returns a new key of the specified type with the same annotation as this * key. * * @since 3.0 */ public Key ofType(TypeLiteral type) { return new Key(type, annotationStrategy); } /** * Returns true if this key has annotation attributes. * * @since 3.0 */ public boolean hasAttributes() { return annotationStrategy.hasAttributes(); } /** * Returns this key without annotation attributes, i.e. with only the * annotation type. * * @since 3.0 */ public Key withoutAttributes() { return new Key(typeLiteral, annotationStrategy.withoutAttributes()); } interface AnnotationStrategy { Annotation getAnnotation(); Class getAnnotationType(); boolean hasAttributes(); AnnotationStrategy withoutAttributes(); } /** * Gets the strategy for an annotation. */ static AnnotationStrategy strategyFor(Annotation annotation) { checkNotNull(annotation, "annotation"); Class annotationType = annotation.annotationType(); ensureRetainedAtRuntime(annotationType); ensureIsBindingAnnotation(annotationType); if (Annotations.isMarker(annotationType)) { return new AnnotationTypeStrategy(annotationType, annotation); } return new AnnotationInstanceStrategy(Annotations.canonicalizeIfNamed(annotation)); } /** * Gets the strategy for an annotation type. */ static AnnotationStrategy strategyFor(Class annotationType) { checkNotNull(annotationType, "annotation type"); ensureRetainedAtRuntime(annotationType); ensureIsBindingAnnotation(annotationType); return new AnnotationTypeStrategy(Annotations.canonicalizeIfNamed(annotationType), null); } private static void ensureRetainedAtRuntime( Class annotationType) { checkArgument(Annotations.isRetainedAtRuntime(annotationType), "%s is not retained at runtime. Please annotate it with @Retention(RUNTIME).", annotationType.getName()); } private static void ensureIsBindingAnnotation(Class annotationType) { checkArgument(Annotations.isBindingAnnotation(annotationType), "%s is not a binding annotation. Please annotate it with @BindingAnnotation.", annotationType.getName()); } static enum NullAnnotationStrategy implements AnnotationStrategy { INSTANCE; public boolean hasAttributes() { return false; } public AnnotationStrategy withoutAttributes() { throw new UnsupportedOperationException("Key already has no attributes."); } public Annotation getAnnotation() { return null; } public Class getAnnotationType() { return null; } @Override public String toString() { return "[none]"; } } // this class not test-covered static class AnnotationInstanceStrategy implements AnnotationStrategy { final Annotation annotation; AnnotationInstanceStrategy(Annotation annotation) { this.annotation = checkNotNull(annotation, "annotation"); } public boolean hasAttributes() { return true; } public AnnotationStrategy withoutAttributes() { return new AnnotationTypeStrategy(getAnnotationType(), annotation); } public Annotation getAnnotation() { return annotation; } public Class getAnnotationType() { return annotation.annotationType(); } @Override public boolean equals(Object o) { if (!(o instanceof AnnotationInstanceStrategy)) { return false; } AnnotationInstanceStrategy other = (AnnotationInstanceStrategy) o; return annotation.equals(other.annotation); } @Override public int hashCode() { return annotation.hashCode(); } @Override public String toString() { return annotation.toString(); } } static class AnnotationTypeStrategy implements AnnotationStrategy { final Class annotationType; // Keep the instance around if we have it so the client can request it. final Annotation annotation; AnnotationTypeStrategy(Class annotationType, Annotation annotation) { this.annotationType = checkNotNull(annotationType, "annotation type"); this.annotation = annotation; } public boolean hasAttributes() { return false; } public AnnotationStrategy withoutAttributes() { throw new UnsupportedOperationException("Key already has no attributes."); } public Annotation getAnnotation() { return annotation; } public Class getAnnotationType() { return annotationType; } @Override public boolean equals(Object o) { if (!(o instanceof AnnotationTypeStrategy)) { return false; } AnnotationTypeStrategy other = (AnnotationTypeStrategy) o; return annotationType.equals(other.annotationType); } @Override public int hashCode() { return annotationType.hashCode(); } @Override public String toString() { return "@" + annotationType.getName(); } } } guice-3.0/core/src/com/google/inject/PrivateModule.java0000644000175000017500000002174511460133000023011 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.binder.AnnotatedConstantBindingBuilder; import com.google.inject.binder.AnnotatedElementBuilder; import com.google.inject.binder.LinkedBindingBuilder; import static com.google.inject.internal.util.Preconditions.checkState; import com.google.inject.matcher.Matcher; import com.google.inject.spi.Message; import com.google.inject.spi.TypeConverter; import com.google.inject.spi.TypeListener; import java.lang.annotation.Annotation; import java.lang.reflect.Method; /** * A module whose configuration information is hidden from its environment by default. Only bindings * that are explicitly exposed will be available to other modules and to the users of the injector. * This module may expose the bindings it creates and the bindings of the modules it installs. * *

A private module can be nested within a regular module or within another private module using * {@link Binder#install install()}. Its bindings live in a new environment that inherits bindings, * type converters, scopes, and interceptors from the surrounding ("parent") environment. When you * nest multiple private modules, the result is a tree of environments where the injector's * environment is the root. * *

Guice EDSL bindings can be exposed with {@link #expose(Class) expose()}. {@literal @}{@link * com.google.inject.Provides Provides} bindings can be exposed with the {@literal @}{@link * Exposed} annotation: * *

 * public class FooBarBazModule extends PrivateModule {
 *   protected void configure() {
 *     bind(Foo.class).to(RealFoo.class);
 *     expose(Foo.class);
 *
 *     install(new TransactionalBarModule());
 *     expose(Bar.class).annotatedWith(Transactional.class);
 *
 *     bind(SomeImplementationDetail.class);
 *     install(new MoreImplementationDetailsModule());
 *   }
 *
 *   {@literal @}Provides {@literal @}Exposed
 *   public Baz provideBaz() {
 *     return new SuperBaz();
 *   }
 * }
 * 
* *

Private modules are implemented using {@link Injector#createChildInjector(Module[]) parent * injectors}. When it can satisfy their dependencies, just-in-time bindings will be created in the * root environment. Such bindings are shared among all environments in the tree. * *

The scope of a binding is constrained to its environment. A singleton bound in a private * module will be unique to its environment. But a binding for the same type in a different private * module will yield a different instance. * *

A shared binding that injects the {@code Injector} gets the root injector, which only has * access to bindings in the root environment. An explicit binding that injects the {@code Injector} * gets access to all bindings in the child environment. * *

To promote a just-in-time binding to an explicit binding, bind it: *

 *   bind(FooImpl.class);
 * 
* * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public abstract class PrivateModule implements Module { /** Like abstract module, the binder of the current private module */ private PrivateBinder binder; public final synchronized void configure(Binder binder) { checkState(this.binder == null, "Re-entry is not allowed."); // Guice treats PrivateModules specially and passes in a PrivateBinder automatically. this.binder = (PrivateBinder) binder.skipSources(PrivateModule.class); try { configure(); } finally { this.binder = null; } } /** * Creates bindings and other configurations private to this module. Use {@link #expose(Class) * expose()} to make the bindings in this module available externally. */ protected abstract void configure(); /** Makes the binding for {@code key} available to other modules and the injector. */ protected final void expose(Key key) { binder.expose(key); } /** * Makes a binding for {@code type} available to other modules and the injector. Use {@link * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a * binding annotation. */ protected final AnnotatedElementBuilder expose(Class type) { return binder.expose(type); } /** * Makes a binding for {@code type} available to other modules and the injector. Use {@link * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a * binding annotation. */ protected final AnnotatedElementBuilder expose(TypeLiteral type) { return binder.expose(type); } // everything below is copied from AbstractModule /** * Returns the current binder. */ protected final PrivateBinder binder() { return binder; } /** * @see Binder#bindScope(Class, Scope) */ protected final void bindScope(Class scopeAnnotation, Scope scope) { binder.bindScope(scopeAnnotation, scope); } /** * @see Binder#bind(Key) */ protected final LinkedBindingBuilder bind(Key key) { return binder.bind(key); } /** * @see Binder#bind(TypeLiteral) */ protected final AnnotatedBindingBuilder bind(TypeLiteral typeLiteral) { return binder.bind(typeLiteral); } /** * @see Binder#bind(Class) */ protected final AnnotatedBindingBuilder bind(Class clazz) { return binder.bind(clazz); } /** * @see Binder#bindConstant() */ protected final AnnotatedConstantBindingBuilder bindConstant() { return binder.bindConstant(); } /** * @see Binder#install(Module) */ protected final void install(Module module) { binder.install(module); } /** * @see Binder#addError(String, Object[]) */ protected final void addError(String message, Object... arguments) { binder.addError(message, arguments); } /** * @see Binder#addError(Throwable) */ protected final void addError(Throwable t) { binder.addError(t); } /** * @see Binder#addError(Message) */ protected final void addError(Message message) { binder.addError(message); } /** * @see Binder#requestInjection(Object) */ protected final void requestInjection(Object instance) { binder.requestInjection(instance); } /** * @see Binder#requestStaticInjection(Class[]) */ protected final void requestStaticInjection(Class... types) { binder.requestStaticInjection(types); } /*if[AOP]*/ /** * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher, com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[]) */ protected final void bindInterceptor(Matcher> classMatcher, Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors) { binder.bindInterceptor(classMatcher, methodMatcher, interceptors); } /*end[AOP]*/ /** * Instructs Guice to require a binding to the given key. */ protected final void requireBinding(Key key) { binder.getProvider(key); } /** * Instructs Guice to require a binding to the given type. */ protected final void requireBinding(Class type) { binder.getProvider(type); } /** * @see Binder#getProvider(Key) */ protected final Provider getProvider(Key key) { return binder.getProvider(key); } /** * @see Binder#getProvider(Class) */ protected final Provider getProvider(Class type) { return binder.getProvider(type); } /** * @see Binder#convertToTypes(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeConverter) */ protected final void convertToTypes(Matcher> typeMatcher, TypeConverter converter) { binder.convertToTypes(typeMatcher, converter); } /** * @see Binder#currentStage() */ protected final Stage currentStage() { return binder.currentStage(); } /** * @see Binder#getMembersInjector(Class) */ protected MembersInjector getMembersInjector(Class type) { return binder.getMembersInjector(type); } /** * @see Binder#getMembersInjector(TypeLiteral) */ protected MembersInjector getMembersInjector(TypeLiteral type) { return binder.getMembersInjector(type); } /** * @see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener) */ protected void bindListener(Matcher> typeMatcher, TypeListener listener) { binder.bindListener(typeMatcher, listener); } } guice-3.0/core/src/com/google/inject/BindingAnnotation.java0000644000175000017500000000251711460133000023632 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Annotates annotations which are used for binding. Only one such annotation * may apply to a single injection point. You must also annotate binder * annotations with {@code @Retention(RUNTIME)}. For example: * *
 *   {@code @}Retention(RUNTIME)
 *   {@code @}Target({ FIELD, PARAMETER, METHOD })
 *   {@code @}BindingAnnotation
 *   public {@code @}interface Transactional {}
 * 
* * @author crazybob@google.com (Bob Lee) */ @Target(ANNOTATION_TYPE) @Retention(RUNTIME) public @interface BindingAnnotation {} guice-3.0/core/src/com/google/inject/ImplementedBy.java0000644000175000017500000000203511460133000022756 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * A pointer to the default implementation of a type. * * @author crazybob@google.com (Bob Lee) */ @Retention(RUNTIME) @Target(TYPE) public @interface ImplementedBy { /** * The implementation type. */ Class value(); } guice-3.0/core/src/com/google/inject/matcher/0000755000175000017500000000000011460132772021017 5ustar drazzibdrazzibguice-3.0/core/src/com/google/inject/matcher/package-info.java0000644000175000017500000000134111460132772024205 0ustar drazzibdrazzib/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Used for matching things. Primarily used to pick out methods to which to * apply interceptors. */ package com.google.inject.matcher;guice-3.0/core/src/com/google/inject/matcher/AbstractMatcher.java0000644000175000017500000000477011460132772024741 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.matcher; import java.io.Serializable; /** * Implements {@code and()} and {@code or()}. * * @author crazybob@google.com (Bob Lee) */ public abstract class AbstractMatcher implements Matcher { public Matcher and(final Matcher other) { return new AndMatcher(this, other); } public Matcher or(Matcher other) { return new OrMatcher(this, other); } private static class AndMatcher extends AbstractMatcher implements Serializable { private final Matcher a, b; public AndMatcher(Matcher a, Matcher b) { this.a = a; this.b = b; } public boolean matches(T t) { return a.matches(t) && b.matches(t); } @Override public boolean equals(Object other) { return other instanceof AndMatcher && ((AndMatcher) other).a.equals(a) && ((AndMatcher) other).b.equals(b); } @Override public int hashCode() { return 41 * (a.hashCode() ^ b.hashCode()); } @Override public String toString() { return "and(" + a + ", " + b + ")"; } private static final long serialVersionUID = 0; } private static class OrMatcher extends AbstractMatcher implements Serializable { private final Matcher a, b; public OrMatcher(Matcher a, Matcher b) { this.a = a; this.b = b; } public boolean matches(T t) { return a.matches(t) || b.matches(t); } @Override public boolean equals(Object other) { return other instanceof OrMatcher && ((OrMatcher) other).a.equals(a) && ((OrMatcher) other).b.equals(b); } @Override public int hashCode() { return 37 * (a.hashCode() ^ b.hashCode()); } @Override public String toString() { return "or(" + a + ", " + b + ")"; } private static final long serialVersionUID = 0; } } guice-3.0/core/src/com/google/inject/matcher/Matchers.java0000644000175000017500000002653611460132772023444 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.matcher; import static com.google.inject.internal.util.Preconditions.checkArgument; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; /** * Matcher implementations. Supports matching classes and methods. * * @author crazybob@google.com (Bob Lee) */ public class Matchers { private Matchers() {} /** * Returns a matcher which matches any input. */ public static Matcher any() { return ANY; } private static final Matcher ANY = new Any(); private static class Any extends AbstractMatcher implements Serializable { public boolean matches(Object o) { return true; } @Override public String toString() { return "any()"; } public Object readResolve() { return any(); } private static final long serialVersionUID = 0; } /** * Inverts the given matcher. */ public static Matcher not(final Matcher p) { return new Not(p); } private static class Not extends AbstractMatcher implements Serializable { final Matcher delegate; private Not(Matcher delegate) { this.delegate = checkNotNull(delegate, "delegate"); } public boolean matches(T t) { return !delegate.matches(t); } @Override public boolean equals(Object other) { return other instanceof Not && ((Not) other).delegate.equals(delegate); } @Override public int hashCode() { return -delegate.hashCode(); } @Override public String toString() { return "not(" + delegate + ")"; } private static final long serialVersionUID = 0; } private static void checkForRuntimeRetention( Class annotationType) { Retention retention = annotationType.getAnnotation(Retention.class); checkArgument(retention != null && retention.value() == RetentionPolicy.RUNTIME, "Annotation " + annotationType.getSimpleName() + " is missing RUNTIME retention"); } /** * Returns a matcher which matches elements (methods, classes, etc.) * with a given annotation. */ public static Matcher annotatedWith( final Class annotationType) { return new AnnotatedWithType(annotationType); } private static class AnnotatedWithType extends AbstractMatcher implements Serializable { private final Class annotationType; public AnnotatedWithType(Class annotationType) { this.annotationType = checkNotNull(annotationType, "annotation type"); checkForRuntimeRetention(annotationType); } public boolean matches(AnnotatedElement element) { return element.getAnnotation(annotationType) != null; } @Override public boolean equals(Object other) { return other instanceof AnnotatedWithType && ((AnnotatedWithType) other).annotationType.equals(annotationType); } @Override public int hashCode() { return 37 * annotationType.hashCode(); } @Override public String toString() { return "annotatedWith(" + annotationType.getSimpleName() + ".class)"; } private static final long serialVersionUID = 0; } /** * Returns a matcher which matches elements (methods, classes, etc.) * with a given annotation. */ public static Matcher annotatedWith( final Annotation annotation) { return new AnnotatedWith(annotation); } private static class AnnotatedWith extends AbstractMatcher implements Serializable { private final Annotation annotation; public AnnotatedWith(Annotation annotation) { this.annotation = checkNotNull(annotation, "annotation"); checkForRuntimeRetention(annotation.annotationType()); } public boolean matches(AnnotatedElement element) { Annotation fromElement = element.getAnnotation(annotation.annotationType()); return fromElement != null && annotation.equals(fromElement); } @Override public boolean equals(Object other) { return other instanceof AnnotatedWith && ((AnnotatedWith) other).annotation.equals(annotation); } @Override public int hashCode() { return 37 * annotation.hashCode(); } @Override public String toString() { return "annotatedWith(" + annotation + ")"; } private static final long serialVersionUID = 0; } /** * Returns a matcher which matches subclasses of the given type (as well as * the given type). */ public static Matcher subclassesOf(final Class superclass) { return new SubclassesOf(superclass); } private static class SubclassesOf extends AbstractMatcher implements Serializable { private final Class superclass; public SubclassesOf(Class superclass) { this.superclass = checkNotNull(superclass, "superclass"); } public boolean matches(Class subclass) { return superclass.isAssignableFrom(subclass); } @Override public boolean equals(Object other) { return other instanceof SubclassesOf && ((SubclassesOf) other).superclass.equals(superclass); } @Override public int hashCode() { return 37 * superclass.hashCode(); } @Override public String toString() { return "subclassesOf(" + superclass.getSimpleName() + ".class)"; } private static final long serialVersionUID = 0; } /** * Returns a matcher which matches objects equal to the given object. */ public static Matcher only(Object value) { return new Only(value); } private static class Only extends AbstractMatcher implements Serializable { private final Object value; public Only(Object value) { this.value = checkNotNull(value, "value"); } public boolean matches(Object other) { return value.equals(other); } @Override public boolean equals(Object other) { return other instanceof Only && ((Only) other).value.equals(value); } @Override public int hashCode() { return 37 * value.hashCode(); } @Override public String toString() { return "only(" + value + ")"; } private static final long serialVersionUID = 0; } /** * Returns a matcher which matches only the given object. */ public static Matcher identicalTo(final Object value) { return new IdenticalTo(value); } private static class IdenticalTo extends AbstractMatcher implements Serializable { private final Object value; public IdenticalTo(Object value) { this.value = checkNotNull(value, "value"); } public boolean matches(Object other) { return value == other; } @Override public boolean equals(Object other) { return other instanceof IdenticalTo && ((IdenticalTo) other).value == value; } @Override public int hashCode() { return 37 * System.identityHashCode(value); } @Override public String toString() { return "identicalTo(" + value + ")"; } private static final long serialVersionUID = 0; } /** * Returns a matcher which matches classes in the given package. Packages are specific to their * classloader, so classes with the same package name may not have the same package at runtime. */ public static Matcher inPackage(final Package targetPackage) { return new InPackage(targetPackage); } private static class InPackage extends AbstractMatcher implements Serializable { private final transient Package targetPackage; private final String packageName; public InPackage(Package targetPackage) { this.targetPackage = checkNotNull(targetPackage, "package"); this.packageName = targetPackage.getName(); } public boolean matches(Class c) { return c.getPackage().equals(targetPackage); } @Override public boolean equals(Object other) { return other instanceof InPackage && ((InPackage) other).targetPackage.equals(targetPackage); } @Override public int hashCode() { return 37 * targetPackage.hashCode(); } @Override public String toString() { return "inPackage(" + targetPackage.getName() + ")"; } public Object readResolve() { return inPackage(Package.getPackage(packageName)); } private static final long serialVersionUID = 0; } /** * Returns a matcher which matches classes in the given package and its subpackages. Unlike * {@link #inPackage(Package) inPackage()}, this matches classes from any classloader. * * @since 2.0 */ public static Matcher inSubpackage(final String targetPackageName) { return new InSubpackage(targetPackageName); } private static class InSubpackage extends AbstractMatcher implements Serializable { private final String targetPackageName; public InSubpackage(String targetPackageName) { this.targetPackageName = targetPackageName; } public boolean matches(Class c) { String classPackageName = c.getPackage().getName(); return classPackageName.equals(targetPackageName) || classPackageName.startsWith(targetPackageName + "."); } @Override public boolean equals(Object other) { return other instanceof InSubpackage && ((InSubpackage) other).targetPackageName.equals(targetPackageName); } @Override public int hashCode() { return 37 * targetPackageName.hashCode(); } @Override public String toString() { return "inSubpackage(" + targetPackageName + ")"; } private static final long serialVersionUID = 0; } /** * Returns a matcher which matches methods with matching return types. */ public static Matcher returns( final Matcher> returnType) { return new Returns(returnType); } private static class Returns extends AbstractMatcher implements Serializable { private final Matcher> returnType; public Returns(Matcher> returnType) { this.returnType = checkNotNull(returnType, "return type matcher"); } public boolean matches(Method m) { return returnType.matches(m.getReturnType()); } @Override public boolean equals(Object other) { return other instanceof Returns && ((Returns) other).returnType.equals(returnType); } @Override public int hashCode() { return 37 * returnType.hashCode(); } @Override public String toString() { return "returns(" + returnType + ")"; } private static final long serialVersionUID = 0; } } guice-3.0/core/src/com/google/inject/matcher/Matcher.java0000644000175000017500000000232411460132772023246 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.matcher; /** * Returns {@code true} or {@code false} for a given input. * * @author crazybob@google.com (Bob Lee) */ public interface Matcher { /** * Returns {@code true} if this matches {@code t}, {@code false} otherwise. */ boolean matches(T t); /** * Returns a new matcher which returns {@code true} if both this and the * given matcher return {@code true}. */ Matcher and(Matcher other); /** * Returns a new matcher which returns {@code true} if either this or the * given matcher return {@code true}. */ Matcher or(Matcher other); } guice-3.0/core/src/com/google/inject/util/0000755000175000017500000000000011477770404020361 5ustar drazzibdrazzibguice-3.0/core/src/com/google/inject/util/Modules.java0000644000175000017500000002663011460133000022614 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.util; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.PrivateBinder; import com.google.inject.PrivateModule; import com.google.inject.Scope; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Iterables; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Maps; import com.google.inject.internal.util.Sets; import com.google.inject.spi.DefaultBindingScopingVisitor; import com.google.inject.spi.DefaultElementVisitor; import com.google.inject.spi.Element; import com.google.inject.spi.Elements; import com.google.inject.spi.PrivateElements; import com.google.inject.spi.ScopeBinding; import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Static utility methods for creating and working with instances of {@link Module}. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class Modules { private Modules() {} public static final Module EMPTY_MODULE = new Module() { public void configure(Binder binder) {} }; /** * Returns a builder that creates a module that overlays override modules over the given * modules. If a key is bound in both sets of modules, only the binding from the override modules * is kept. If a single {@link PrivateModule} is supplied or all elements are from * a single {@link PrivateBinder}, then this will overwrite the private bindings. * Otherwise, private bindings will not be overwritten unless they are exposed. * This can be used to replace the bindings of a production module with test bindings: *
   * Module functionalTestModule
   *     = Modules.override(new ProductionModule()).with(new TestModule());
   * 
* *

Prefer to write smaller modules that can be reused and tested without overrides. * * @param modules the modules whose bindings are open to be overridden */ public static OverriddenModuleBuilder override(Module... modules) { return new RealOverriddenModuleBuilder(Arrays.asList(modules)); } /** * Returns a builder that creates a module that overlays override modules over the given * modules. If a key is bound in both sets of modules, only the binding from the override modules * is kept. If a single {@link PrivateModule} is supplied or all elements are from * a single {@link PrivateBinder}, then this will overwrite the private bindings. * Otherwise, private bindings will not be overwritten unless they are exposed. * This can be used to replace the bindings of a production module with test bindings: *

   * Module functionalTestModule
   *     = Modules.override(getProductionModules()).with(getTestModules());
   * 
* *

Prefer to write smaller modules that can be reused and tested without overrides. * * @param modules the modules whose bindings are open to be overridden */ public static OverriddenModuleBuilder override(Iterable modules) { return new RealOverriddenModuleBuilder(modules); } /** * Returns a new module that installs all of {@code modules}. */ public static Module combine(Module... modules) { return combine(ImmutableSet.of(modules)); } /** * Returns a new module that installs all of {@code modules}. */ public static Module combine(Iterable modules) { final Set modulesSet = ImmutableSet.copyOf(modules); return new Module() { public void configure(Binder binder) { binder = binder.skipSources(getClass()); for (Module module : modulesSet) { binder.install(module); } } }; } /** * See the EDSL example at {@link Modules#override(Module[]) override()}. */ public interface OverriddenModuleBuilder { /** * See the EDSL example at {@link Modules#override(Module[]) override()}. */ Module with(Module... overrides); /** * See the EDSL example at {@link Modules#override(Module[]) override()}. */ Module with(Iterable overrides); } private static final class RealOverriddenModuleBuilder implements OverriddenModuleBuilder { private final ImmutableSet baseModules; private RealOverriddenModuleBuilder(Iterable baseModules) { this.baseModules = ImmutableSet.copyOf(baseModules); } public Module with(Module... overrides) { return with(Arrays.asList(overrides)); } public Module with(final Iterable overrides) { return new AbstractModule() { @Override public void configure() { Binder baseBinder = binder(); List baseElements = Elements.getElements(baseModules); // If the sole element was a PrivateElements, we want to override // the private elements within that -- so refocus our elements // and binder. if(baseElements.size() == 1) { Element element = Iterables.getOnlyElement(baseElements); if(element instanceof PrivateElements) { PrivateElements privateElements = (PrivateElements)element; PrivateBinder privateBinder = baseBinder.newPrivateBinder().withSource(privateElements.getSource()); for(Key exposed : privateElements.getExposedKeys()) { privateBinder.withSource(privateElements.getExposedSource(exposed)).expose(exposed); } baseBinder = privateBinder; baseElements = privateElements.getElements(); } } final Binder binder = baseBinder; final LinkedHashSet elements = new LinkedHashSet(baseElements); final List overrideElements = Elements.getElements(overrides); final Set> overriddenKeys = Sets.newHashSet(); final Set> overridesScopeAnnotations = Sets.newHashSet(); // execute the overrides module, keeping track of which keys and scopes are bound new ModuleWriter(binder) { @Override public Void visit(Binding binding) { overriddenKeys.add(binding.getKey()); return super.visit(binding); } @Override public Void visit(ScopeBinding scopeBinding) { overridesScopeAnnotations.add(scopeBinding.getAnnotationType()); return super.visit(scopeBinding); } @Override public Void visit(PrivateElements privateElements) { overriddenKeys.addAll(privateElements.getExposedKeys()); return super.visit(privateElements); } }.writeAll(overrideElements); // execute the original module, skipping all scopes and overridden keys. We only skip each // overridden binding once so things still blow up if the module binds the same thing // multiple times. final Map scopeInstancesInUse = Maps.newHashMap(); final List scopeBindings = Lists.newArrayList(); new ModuleWriter(binder) { @Override public Void visit(Binding binding) { if (!overriddenKeys.remove(binding.getKey())) { super.visit(binding); // Record when a scope instance is used in a binding Scope scope = getScopeInstanceOrNull(binding); if (scope != null) { scopeInstancesInUse.put(scope, binding.getSource()); } } return null; } void rewrite(Binder binder, PrivateElements privateElements, Set> keysToSkip) { PrivateBinder privateBinder = binder.withSource(privateElements.getSource()) .newPrivateBinder(); Set> skippedExposes = Sets.newHashSet(); for (Key key : privateElements.getExposedKeys()) { if (keysToSkip.remove(key)) { skippedExposes.add(key); } else { privateBinder.withSource(privateElements.getExposedSource(key)).expose(key); } } for (Element element : privateElements.getElements()) { if (element instanceof Binding && skippedExposes.remove(((Binding) element).getKey())) { continue; } if (element instanceof PrivateElements) { rewrite(privateBinder, (PrivateElements) element, skippedExposes); continue; } element.applyTo(privateBinder); } } @Override public Void visit(PrivateElements privateElements) { rewrite(binder, privateElements, overriddenKeys); return null; } @Override public Void visit(ScopeBinding scopeBinding) { scopeBindings.add(scopeBinding); return null; } }.writeAll(elements); // execute the scope bindings, skipping scopes that have been overridden. Any scope that // is overridden and in active use will prompt an error new ModuleWriter(binder) { @Override public Void visit(ScopeBinding scopeBinding) { if (!overridesScopeAnnotations.remove(scopeBinding.getAnnotationType())) { super.visit(scopeBinding); } else { Object source = scopeInstancesInUse.get(scopeBinding.getScope()); if (source != null) { binder.withSource(source).addError( "The scope for @%s is bound directly and cannot be overridden.", scopeBinding.getAnnotationType().getSimpleName()); } } return null; } }.writeAll(scopeBindings); // TODO: bind the overridden keys using multibinder } private Scope getScopeInstanceOrNull(Binding binding) { return binding.acceptScopingVisitor(new DefaultBindingScopingVisitor() { public Scope visitScope(Scope scope) { return scope; } }); } }; } } private static class ModuleWriter extends DefaultElementVisitor { protected final Binder binder; ModuleWriter(Binder binder) { this.binder = binder; } @Override protected Void visitOther(Element element) { element.applyTo(binder); return null; } void writeAll(Iterable elements) { for (Element element : elements) { element.acceptVisitor(this); } } } } guice-3.0/core/src/com/google/inject/util/package-info.java0000644000175000017500000000124511460133000023523 0ustar drazzibdrazzib/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Helper methods for working with Guice. */ package com.google.inject.util;guice-3.0/core/src/com/google/inject/util/Node.java0000644000175000017500000000657711460133000022101 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.util; import com.google.inject.Key; import com.google.inject.internal.Errors; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Sets; import java.lang.annotation.Annotation; import java.util.Set; /** * A node in the scoped dependency graph. Each node has two scopes. The applied scope is the * scope directly assigned to the binding by the user, such as in an {@code in()} clause. The * effective scope is the narrowest scope in which this object is used. It is derived from * the narrowest scope of the node's transitive dependencies. Each scope is modelled as a rank; * higher numbers represent narrower scopes. */ class Node { private final Key key; private int appliedScope = Integer.MAX_VALUE; private Node effectiveScopeDependency; private int effectiveScope = Integer.MIN_VALUE; private Class appliedScopeAnnotation; /** Places that this node is injected. */ private Set users = ImmutableSet.of(); Node(Key key) { this.key = key; } /** * Initialize the scope ranks for this node. Called at most once per node. */ void setScopeRank(int rank, Class annotation) { this.appliedScope = rank; this.effectiveScope = rank; this.appliedScopeAnnotation = annotation; } /** * Sets this node's effective scope unless it's already better. */ private void setEffectiveScope(int effectiveScope, Node effectiveScopeDependency) { if (this.effectiveScope >= effectiveScope) { return; } this.effectiveScope = effectiveScope; this.effectiveScopeDependency = effectiveScopeDependency; pushScopeToUsers(); } /** * Pushes the narrowness of this node's effective scope to everyone that depends on this node. */ void pushScopeToUsers() { for (Node user : users) { user.setEffectiveScope(effectiveScope, this); } } /** * Returns true if this node has no dependency whose scope is narrower than itself. */ boolean isScopedCorrectly() { return appliedScope >= effectiveScope; } boolean isEffectiveScopeAppliedScope() { return appliedScope == effectiveScope; } /** * Returns the most narrowly scoped dependency. If multiple such dependencies exist, the selection * of which is returned is arbitrary. */ Node effectiveScopeDependency() { return effectiveScopeDependency; } /** * Mark this as a dependency of {@code node}. */ public void addUser(Node node) { if (users.isEmpty()) { users = Sets.newHashSet(); } users.add(node); } @Override public String toString() { return appliedScopeAnnotation != null ? Errors.convert(key) + " in @" + appliedScopeAnnotation.getSimpleName() : Errors.convert(key).toString(); } } guice-3.0/core/src/com/google/inject/util/Providers.java0000644000175000017500000000733211500106306023163 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.util; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.util.Set; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Provider; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Sets; import com.google.inject.spi.Dependency; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.ProviderWithDependencies; /** * Static utility methods for creating and working with instances of * {@link Provider}. * * @author Kevin Bourrillion (kevinb9n@gmail.com) * @since 2.0 */ public final class Providers { private Providers() {} /** * Returns a provider which always provides {@code instance}. This should not * be necessary to use in your application, but is helpful for several types * of unit tests. * * @param instance the instance that should always be provided. This is also * permitted to be null, to enable aggressive testing, although in real * life a Guice-supplied Provider will never return null. */ public static Provider of(final T instance) { return new Provider() { public T get() { return instance; } @Override public String toString() { return "of(" + instance + ")"; } }; } /** * Returns a Guice-friendly {@code com.google.inject.Provider} for the given * JSR-330 {@code javax.inject.Provider}. The converse method is unnecessary, * since Guice providers directly implement the JSR-330 interface. * * @since 3.0 */ public static Provider guicify(javax.inject.Provider provider) { if (provider instanceof Provider) { return (Provider) provider; } final javax.inject.Provider delegate = checkNotNull(provider, "provider"); // Ensure that we inject all injection points from the delegate provider. Set injectionPoints = InjectionPoint.forInstanceMethodsAndFields(provider.getClass()); if(injectionPoints.isEmpty()) { return new Provider() { public T get() { return delegate.get(); } @Override public String toString() { return "guicified(" + delegate + ")"; } }; } else { Set> mutableDeps = Sets.newHashSet(); for(InjectionPoint ip : injectionPoints) { mutableDeps.addAll(ip.getDependencies()); } final Set> dependencies = ImmutableSet.copyOf(mutableDeps); return new ProviderWithDependencies() { @SuppressWarnings("unused") @Inject void initialize(Injector injector) { injector.injectMembers(delegate); } public Set> getDependencies() { return dependencies; } public T get() { return delegate.get(); } @Override public String toString() { return "guicified(" + delegate + ")"; } }; } } } guice-3.0/core/src/com/google/inject/util/Types.java0000644000175000017500000001103011460133000022274 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.util; import com.google.inject.Provider; import com.google.inject.internal.MoreTypes; import com.google.inject.internal.MoreTypes.GenericArrayTypeImpl; import com.google.inject.internal.MoreTypes.ParameterizedTypeImpl; import com.google.inject.internal.MoreTypes.WildcardTypeImpl; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.util.List; import java.util.Map; import java.util.Set; /** * Static methods for working with types. * * @author crazybob@google.com (Bob Lee) * @since 2.0 */ public final class Types { private Types() {} /** * Returns a new parameterized type, applying {@code typeArguments} to * {@code rawType}. The returned type does not have an owner type. * * @return a {@link java.io.Serializable serializable} parameterized type. */ public static ParameterizedType newParameterizedType(Type rawType, Type... typeArguments) { return newParameterizedTypeWithOwner(null, rawType, typeArguments); } /** * Returns a new parameterized type, applying {@code typeArguments} to * {@code rawType} and enclosed by {@code ownerType}. * * @return a {@link java.io.Serializable serializable} parameterized type. */ public static ParameterizedType newParameterizedTypeWithOwner( Type ownerType, Type rawType, Type... typeArguments) { return new ParameterizedTypeImpl(ownerType, rawType, typeArguments); } /** * Returns an array type whose elements are all instances of * {@code componentType}. * * @return a {@link java.io.Serializable serializable} generic array type. */ public static GenericArrayType arrayOf(Type componentType) { return new GenericArrayTypeImpl(componentType); } /** * Returns a type that represents an unknown type that extends {@code bound}. * For example, if {@code bound} is {@code CharSequence.class}, this returns * {@code ? extends CharSequence}. If {@code bound} is {@code Object.class}, * this returns {@code ?}, which is shorthand for {@code ? extends Object}. */ public static WildcardType subtypeOf(Type bound) { return new WildcardTypeImpl(new Type[] { bound }, MoreTypes.EMPTY_TYPE_ARRAY); } /** * Returns a type that represents an unknown supertype of {@code bound}. For * example, if {@code bound} is {@code String.class}, this returns {@code ? * super String}. */ public static WildcardType supertypeOf(Type bound) { return new WildcardTypeImpl(new Type[] { Object.class }, new Type[] { bound }); } /** * Returns a type modelling a {@link List} whose elements are of type * {@code elementType}. * * @return a {@link java.io.Serializable serializable} parameterized type. */ public static ParameterizedType listOf(Type elementType) { return newParameterizedType(List.class, elementType); } /** * Returns a type modelling a {@link Set} whose elements are of type * {@code elementType}. * * @return a {@link java.io.Serializable serializable} parameterized type. */ public static ParameterizedType setOf(Type elementType) { return newParameterizedType(Set.class, elementType); } /** * Returns a type modelling a {@link Map} whose keys are of type * {@code keyType} and whose values are of type {@code valueType}. * * @return a {@link java.io.Serializable serializable} parameterized type. */ public static ParameterizedType mapOf(Type keyType, Type valueType) { return newParameterizedType(Map.class, keyType, valueType); } // for other custom collections types, use newParameterizedType() /** * Returns a type modelling a {@link Provider} that provides elements of type * {@code elementType}. * * @return a {@link java.io.Serializable serializable} parameterized type. */ public static ParameterizedType providerOf(Type providedType) { return newParameterizedType(Provider.class, providedType); } }guice-3.0/core/src/com/google/inject/Exposed.java0000644000175000017500000000222211460133000021625 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Acccompanies a {@literal @}{@link com.google.inject.Provides Provides} method annotation in a * private module to indicate that the provided binding is exposed. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ @Target(ElementType.METHOD) @Retention(RUNTIME) @Documented public @interface Exposed {} guice-3.0/core/src/com/google/inject/ProvidedBy.java0000644000175000017500000000205611460133000022272 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * A pointer to the default provider type for a type. * * @author crazybob@google.com (Bob Lee) */ @Retention(RUNTIME) @Target(TYPE) public @interface ProvidedBy { /** * The implementation type. */ Class> value(); } guice-3.0/core/src/com/google/inject/spi/0000755000175000017500000000000011531414212020156 5ustar drazzibdrazzibguice-3.0/core/src/com/google/inject/spi/ProviderBinding.java0000644000175000017500000000251311460132772024120 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.Provider; /** * A binding to a {@link Provider} that delegates to the binding for the provided type. This binding * is used whenever a {@code Provider} is injected (as opposed to injecting {@code T} directly). * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface ProviderBinding> extends Binding { /** * Returns the key whose binding is used to {@link Provider#get provide instances}. That binding * can be retrieved from an injector using {@link com.google.inject.Injector#getBinding(Key) * Injector.getBinding(providedKey)} */ Key getProvidedKey(); }guice-3.0/core/src/com/google/inject/spi/ProviderKeyBinding.java0000644000175000017500000000236311460132772024574 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; import com.google.inject.Key; /** * A binding to a provider key. To resolve injections, the provider key is first resolved, then that * provider's {@code get} method is invoked. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface ProviderKeyBinding extends Binding { /** * Returns the key used to resolve the provider's binding. That binding can be retrieved from an * injector using {@link com.google.inject.Injector#getBinding(Key) * Injector.getBinding(providerKey)} */ Key> getProviderKey(); }guice-3.0/core/src/com/google/inject/spi/BindingScopingVisitor.java0000644000175000017500000000363011460132772025311 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Scope; import java.lang.annotation.Annotation; /** * Visits each of the strategies used to scope an injection. * * @param any type to be returned by the visit method. Use {@link Void} with * {@code return null} if no return type is needed. * @since 2.0 */ public interface BindingScopingVisitor { /** * Visit an eager singleton or single instance. This scope strategy is found on both module and * injector bindings. */ V visitEagerSingleton(); /** * Visit a scope instance. This scope strategy is found on both module and injector bindings. */ V visitScope(Scope scope); /** * Visit a scope annotation. This scope strategy is found only on module bindings. The instance * that implements this scope is registered by {@link com.google.inject.Binder#bindScope(Class, * Scope) Binder.bindScope()}. */ V visitScopeAnnotation(Class scopeAnnotation); /** * Visit an unspecified or unscoped strategy. On a module, this strategy indicates that the * injector should use scoping annotations to find a scope. On an injector, it indicates that * no scope is applied to the binding. An unscoped binding will behave like a scoped one when it * is linked to a scoped binding. */ V visitNoScoping(); } guice-3.0/core/src/com/google/inject/spi/package-info.java0000644000175000017500000000123711460132772023361 0ustar drazzibdrazzib/* * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Guice service provider interface */ package com.google.inject.spi;guice-3.0/core/src/com/google/inject/spi/ProviderWithDependencies.java0000644000175000017500000000171111460132772025767 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Provider; /** * A provider with dependencies on other injected types. If a {@link Provider} has dependencies that * aren't specified in injections, this interface should be used to expose all dependencies. * * @since 2.0 */ public interface ProviderWithDependencies extends Provider, HasDependencies {} guice-3.0/core/src/com/google/inject/spi/InjectionPoint.java0000644000175000017500000007331011530443570023771 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.ConfigurationException; import com.google.inject.Inject; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.internal.Annotations; import com.google.inject.internal.Errors; import com.google.inject.internal.ErrorsException; import static com.google.inject.internal.MoreTypes.getRawType; import com.google.inject.internal.Nullability; import com.google.inject.internal.util.Classes; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; /** * A constructor, field or method that can receive injections. Typically this is a member with the * {@literal @}{@link Inject} annotation. For non-private, no argument constructors, the member may * omit the annotation. * * @author crazybob@google.com (Bob Lee) * @since 2.0 */ public final class InjectionPoint { private static final Logger logger = Logger.getLogger(InjectionPoint.class.getName()); private final boolean optional; private final Member member; private final TypeLiteral declaringType; private final ImmutableList> dependencies; InjectionPoint(TypeLiteral declaringType, Method method, boolean optional) { this.member = method; this.declaringType = declaringType; this.optional = optional; this.dependencies = forMember(method, declaringType, method.getParameterAnnotations()); } InjectionPoint(TypeLiteral declaringType, Constructor constructor) { this.member = constructor; this.declaringType = declaringType; this.optional = false; this.dependencies = forMember( constructor, declaringType, constructor.getParameterAnnotations()); } InjectionPoint(TypeLiteral declaringType, Field field, boolean optional) { this.member = field; this.declaringType = declaringType; this.optional = optional; Annotation[] annotations = field.getAnnotations(); Errors errors = new Errors(field); Key key = null; try { key = Annotations.getKey(declaringType.getFieldType(field), field, annotations, errors); } catch (ConfigurationException e) { errors.merge(e.getErrorMessages()); } catch (ErrorsException e) { errors.merge(e.getErrors()); } errors.throwConfigurationExceptionIfErrorsExist(); this.dependencies = ImmutableList.>of( newDependency(key, Nullability.allowsNull(annotations), -1)); } private ImmutableList> forMember(Member member, TypeLiteral type, Annotation[][] paramterAnnotations) { Errors errors = new Errors(member); Iterator annotationsIterator = Arrays.asList(paramterAnnotations).iterator(); List> dependencies = Lists.newArrayList(); int index = 0; for (TypeLiteral parameterType : type.getParameterTypes(member)) { try { Annotation[] parameterAnnotations = annotationsIterator.next(); Key key = Annotations.getKey(parameterType, member, parameterAnnotations, errors); dependencies.add(newDependency(key, Nullability.allowsNull(parameterAnnotations), index)); index++; } catch (ConfigurationException e) { errors.merge(e.getErrorMessages()); } catch (ErrorsException e) { errors.merge(e.getErrors()); } } errors.throwConfigurationExceptionIfErrorsExist(); return ImmutableList.copyOf(dependencies); } // This metohd is necessary to create a Dependency with proper generic type information private Dependency newDependency(Key key, boolean allowsNull, int parameterIndex) { return new Dependency(this, key, allowsNull, parameterIndex); } /** * Returns the injected constructor, field, or method. */ public Member getMember() { // TODO: Don't expose the original member (which probably has setAccessible(true)). return member; } /** * Returns the dependencies for this injection point. If the injection point is for a method or * constructor, the dependencies will correspond to that member's parameters. Field injection * points always have a single dependency for the field itself. * * @return a possibly-empty list */ public List> getDependencies() { return dependencies; } /** * Returns true if this injection point shall be skipped if the injector cannot resolve bindings * for all required dependencies. Both explicit bindings (as specified in a module), and implicit * bindings ({@literal @}{@link com.google.inject.ImplementedBy ImplementedBy}, default * constructors etc.) may be used to satisfy optional injection points. */ public boolean isOptional() { return optional; } /** * Returns true if the element is annotated with {@literal @}{@link Toolable}. * * @since 3.0 */ public boolean isToolable() { return ((AnnotatedElement)member).isAnnotationPresent(Toolable.class); } /** * Returns the generic type that defines this injection point. If the member exists on a * parameterized type, the result will include more type information than the member's {@link * Member#getDeclaringClass() raw declaring class}. * * @since 3.0 */ public TypeLiteral getDeclaringType() { return declaringType; } @Override public boolean equals(Object o) { return o instanceof InjectionPoint && member.equals(((InjectionPoint) o).member) && declaringType.equals(((InjectionPoint) o).declaringType); } @Override public int hashCode() { return member.hashCode() ^ declaringType.hashCode(); } @Override public String toString() { return Classes.toString(member); } /** * Returns a new injection point for the specified constructor. If the declaring type of {@code * constructor} is parameterized (such as {@code List}), prefer the overload that includes a * type literal. * * @param constructor any single constructor present on {@code type}. * * @since 3.0 */ public static InjectionPoint forConstructor(Constructor constructor) { return new InjectionPoint(TypeLiteral.get(constructor.getDeclaringClass()), constructor); } /** * Returns a new injection point for the specified constructor of {@code type}. * * @param constructor any single constructor present on {@code type}. * @param type the concrete type that defines {@code constructor}. * * @since 3.0 */ public static InjectionPoint forConstructor( Constructor constructor, TypeLiteral type) { if (type.getRawType() != constructor.getDeclaringClass()) { new Errors(type) .constructorNotDefinedByType(constructor, type) .throwConfigurationExceptionIfErrorsExist(); } return new InjectionPoint(type, constructor); } /** * Returns a new injection point for the injectable constructor of {@code type}. * * @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject}, * or a no-arguments constructor that is not private. * @throws ConfigurationException if there is no injectable constructor, more than one injectable * constructor, or if parameters of the injectable constructor are malformed, such as a * parameter with multiple binding annotations. */ public static InjectionPoint forConstructorOf(TypeLiteral type) { Class rawType = getRawType(type.getType()); Errors errors = new Errors(rawType); Constructor injectableConstructor = null; for (Constructor constructor : rawType.getDeclaredConstructors()) { boolean optional; Inject guiceInject = constructor.getAnnotation(Inject.class); if (guiceInject == null) { javax.inject.Inject javaxInject = constructor.getAnnotation(javax.inject.Inject.class); if (javaxInject == null) { continue; } optional = false; } else { optional = guiceInject.optional(); } if (optional) { errors.optionalConstructor(constructor); } if (injectableConstructor != null) { errors.tooManyConstructors(rawType); } injectableConstructor = constructor; checkForMisplacedBindingAnnotations(injectableConstructor, errors); } errors.throwConfigurationExceptionIfErrorsExist(); if (injectableConstructor != null) { return new InjectionPoint(type, injectableConstructor); } // If no annotated constructor is found, look for a no-arg constructor instead. try { Constructor noArgConstructor = rawType.getDeclaredConstructor(); // Disallow private constructors on non-private classes (unless they have @Inject) if (Modifier.isPrivate(noArgConstructor.getModifiers()) && !Modifier.isPrivate(rawType.getModifiers())) { errors.missingConstructor(rawType); throw new ConfigurationException(errors.getMessages()); } checkForMisplacedBindingAnnotations(noArgConstructor, errors); return new InjectionPoint(type, noArgConstructor); } catch (NoSuchMethodException e) { errors.missingConstructor(rawType); throw new ConfigurationException(errors.getMessages()); } } /** * Returns a new injection point for the injectable constructor of {@code type}. * * @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject}, * or a no-arguments constructor that is not private. * @throws ConfigurationException if there is no injectable constructor, more than one injectable * constructor, or if parameters of the injectable constructor are malformed, such as a * parameter with multiple binding annotations. */ public static InjectionPoint forConstructorOf(Class type) { return forConstructorOf(TypeLiteral.get(type)); } /** * Returns all static method and field injection points on {@code type}. * * @return a possibly empty set of injection points. The set has a specified iteration order. All * fields are returned and then all methods. Within the fields, supertype fields are returned * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as * a field with multiple binding annotations. The exception's {@link * ConfigurationException#getPartialValue() partial value} is a {@code Set} * of the valid injection points. */ public static Set forStaticMethodsAndFields(TypeLiteral type) { Errors errors = new Errors(); Set result = getInjectionPoints(type, true, errors); if (errors.hasErrors()) { throw new ConfigurationException(errors.getMessages()).withPartialValue(result); } return result; } /** * Returns all static method and field injection points on {@code type}. * * @return a possibly empty set of injection points. The set has a specified iteration order. All * fields are returned and then all methods. Within the fields, supertype fields are returned * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as * a field with multiple binding annotations. The exception's {@link * ConfigurationException#getPartialValue() partial value} is a {@code Set} * of the valid injection points. */ public static Set forStaticMethodsAndFields(Class type) { return forStaticMethodsAndFields(TypeLiteral.get(type)); } /** * Returns all instance method and field injection points on {@code type}. * * @return a possibly empty set of injection points. The set has a specified iteration order. All * fields are returned and then all methods. Within the fields, supertype fields are returned * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as * a field with multiple binding annotations. The exception's {@link * ConfigurationException#getPartialValue() partial value} is a {@code Set} * of the valid injection points. */ public static Set forInstanceMethodsAndFields(TypeLiteral type) { Errors errors = new Errors(); Set result = getInjectionPoints(type, false, errors); if (errors.hasErrors()) { throw new ConfigurationException(errors.getMessages()).withPartialValue(result); } return result; } /** * Returns all instance method and field injection points on {@code type}. * * @return a possibly empty set of injection points. The set has a specified iteration order. All * fields are returned and then all methods. Within the fields, supertype fields are returned * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as * a field with multiple binding annotations. The exception's {@link * ConfigurationException#getPartialValue() partial value} is a {@code Set} * of the valid injection points. */ public static Set forInstanceMethodsAndFields(Class type) { return forInstanceMethodsAndFields(TypeLiteral.get(type)); } /** * Returns true if the binding annotation is in the wrong place. */ private static boolean checkForMisplacedBindingAnnotations(Member member, Errors errors) { Annotation misplacedBindingAnnotation = Annotations.findBindingAnnotation( errors, member, ((AnnotatedElement) member).getAnnotations()); if (misplacedBindingAnnotation == null) { return false; } // don't warn about misplaced binding annotations on methods when there's a field with the same // name. In Scala, fields always get accessor methods (that we need to ignore). See bug 242. if (member instanceof Method) { try { if (member.getDeclaringClass().getDeclaredField(member.getName()) != null) { return false; } } catch (NoSuchFieldException ignore) { } } errors.misplacedBindingAnnotation(member, misplacedBindingAnnotation); return true; } /** * Node in the doubly-linked list of injectable members (fields and methods). */ static abstract class InjectableMember { final TypeLiteral declaringType; final boolean optional; final boolean jsr330; InjectableMember previous; InjectableMember next; InjectableMember(TypeLiteral declaringType, Annotation atInject) { this.declaringType = declaringType; if (atInject.annotationType() == javax.inject.Inject.class) { optional = false; jsr330 = true; return; } jsr330 = false; optional = ((Inject) atInject).optional(); } abstract InjectionPoint toInjectionPoint(); } static class InjectableField extends InjectableMember { final Field field; InjectableField(TypeLiteral declaringType, Field field, Annotation atInject) { super(declaringType, atInject); this.field = field; } InjectionPoint toInjectionPoint() { return new InjectionPoint(declaringType, field, optional); } } static class InjectableMethod extends InjectableMember { final Method method; /** * true if this method overrode a method that was annotated * with com.google.inject.Inject. used to allow different * override behavior for guice inject vs javax.inject.Inject */ boolean overrodeGuiceInject; InjectableMethod(TypeLiteral declaringType, Method method, Annotation atInject) { super(declaringType, atInject); this.method = method; } InjectionPoint toInjectionPoint() { return new InjectionPoint(declaringType, method, optional); } public boolean isFinal() { return Modifier.isFinal(method.getModifiers()); } } static Annotation getAtInject(AnnotatedElement member) { Annotation a = member.getAnnotation(javax.inject.Inject.class); return a == null ? member.getAnnotation(Inject.class) : a; } /** * Linked list of injectable members. */ static class InjectableMembers { InjectableMember head; InjectableMember tail; void add(InjectableMember member) { if (head == null) { head = tail = member; } else { member.previous = tail; tail.next = member; tail = member; } } void remove(InjectableMember member) { if (member.previous != null) { member.previous.next = member.next; } if (member.next != null) { member.next.previous = member.previous; } if (head == member) { head = member.next; } if (tail == member) { tail = member.previous; } } boolean isEmpty() { return head == null; } } /** Position in type hierarchy. */ enum Position { TOP, // No need to check for overridden methods MIDDLE, BOTTOM // Methods won't be overridden } /** * Keeps track of injectable methods so we can remove methods that get overridden in O(1) time. * Uses our position in the type hierarchy to perform optimizations. */ static class OverrideIndex { final InjectableMembers injectableMembers; Map> bySignature; Position position = Position.TOP; OverrideIndex(InjectableMembers injectableMembers) { this.injectableMembers = injectableMembers; } /* Caches the signature for the last method. */ Method lastMethod; Signature lastSignature; /** * Removes a method overridden by the given method, if present. In order to * remain backwards compatible with prior Guice versions, this will *not* * remove overridden methods if 'alwaysRemove' is false and the overridden * signature was annotated with a com.google.inject.Inject. * * @param method * The method used to determine what is overridden and should be * removed. * @param alwaysRemove * true if overridden methods should be removed even if they were * guice @Inject * @param injectableMethod * if this method overrode any guice @Inject methods, * {@link InjectableMethod#overrodeGuiceInject} is set to true */ boolean removeIfOverriddenBy(Method method, boolean alwaysRemove, InjectableMethod injectableMethod) { if (position == Position.TOP) { // If we're at the top of the hierarchy, there's nothing to override. return false; } if (bySignature == null) { // We encountered a method in a subclass. Time to index the // methods in the parent class. bySignature = new HashMap>(); for (InjectableMember member = injectableMembers.head; member != null; member = member.next) { if (!(member instanceof InjectableMethod)) continue; InjectableMethod im = (InjectableMethod) member; if (im.isFinal()) continue; List methods = new ArrayList(); methods.add(im); bySignature.put(new Signature(im.method), methods); } } lastMethod = method; Signature signature = lastSignature = new Signature(method); List methods = bySignature.get(signature); boolean removed = false; if (methods != null) { for (Iterator iterator = methods.iterator(); iterator.hasNext();) { InjectableMethod possiblyOverridden = iterator.next(); if (overrides(method, possiblyOverridden.method)) { boolean wasGuiceInject = !possiblyOverridden.jsr330 || possiblyOverridden.overrodeGuiceInject; if(injectableMethod != null) { injectableMethod.overrodeGuiceInject = wasGuiceInject; } // Only actually remove the methods if we want to force // remove or if the signature never specified @com.google.inject.Inject // somewhere. if(alwaysRemove || !wasGuiceInject) { removed = true; iterator.remove(); injectableMembers.remove(possiblyOverridden); } } } } return removed; } /** * Adds the given method to the list of injection points. Keeps track of it in this index * in case it gets overridden. */ void add(InjectableMethod injectableMethod) { injectableMembers.add(injectableMethod); if (position == Position.BOTTOM || injectableMethod.isFinal()) { // This method can't be overridden, so there's no need to index it. return; } if (bySignature != null) { // Try to reuse the signature we created during removal Signature signature = injectableMethod.method == lastMethod ? lastSignature : new Signature(injectableMethod.method); List methods = bySignature.get(signature); if (methods == null) { methods = new ArrayList(); bySignature.put(signature, methods); } methods.add(injectableMethod); } } } /** * Returns an ordered, immutable set of injection points for the given type. Members in * superclasses come before members in subclasses. Within a class, fields come before methods. * Overridden methods are filtered out. * * @param statics true is this method should return static members, false for instance members * @param errors used to record errors */ private static Set getInjectionPoints(final TypeLiteral type, boolean statics, Errors errors) { InjectableMembers injectableMembers = new InjectableMembers(); OverrideIndex overrideIndex = null; List> hierarchy = hierarchyFor(type); int topIndex = hierarchy.size() - 1; for (int i = topIndex; i >= 0; i--) { if (overrideIndex != null && i < topIndex) { // Knowing the position within the hierarchy helps us make optimizations. if (i == 0) { overrideIndex.position = Position.BOTTOM; } else { overrideIndex.position = Position.MIDDLE; } } TypeLiteral current = hierarchy.get(i); for (Field field : current.getRawType().getDeclaredFields()) { if (Modifier.isStatic(field.getModifiers()) == statics) { Annotation atInject = getAtInject(field); if (atInject != null) { InjectableField injectableField = new InjectableField(current, field, atInject); if (injectableField.jsr330 && Modifier.isFinal(field.getModifiers())) { errors.cannotInjectFinalField(field); } injectableMembers.add(injectableField); } } } for (Method method : current.getRawType().getDeclaredMethods()) { if (Modifier.isStatic(method.getModifiers()) == statics) { Annotation atInject = getAtInject(method); if (atInject != null) { InjectableMethod injectableMethod = new InjectableMethod( current, method, atInject); if (checkForMisplacedBindingAnnotations(method, errors) | !isValidMethod(injectableMethod, errors)) { if (overrideIndex != null) { boolean removed = overrideIndex.removeIfOverriddenBy(method, false, injectableMethod); if(removed) { logger.log(Level.WARNING, "Method: {0} is not a valid injectable method (" + "because it either has misplaced binding annotations " + "or specifies type parameters) but is overriding a method that is valid. " + "Because it is not valid, the method will not be injected. " + "To fix this, make the method a valid injectable method.", method); } } continue; } if (statics) { injectableMembers.add(injectableMethod); } else { if (overrideIndex == null) { /* * Creating the override index lazily means that the first type in the hierarchy * with injectable methods (not necessarily the top most type) will be treated as * the TOP position and will enjoy the same optimizations (no checks for overridden * methods, etc.). */ overrideIndex = new OverrideIndex(injectableMembers); } else { // Forcibly remove the overriden method, otherwise we'll inject // it twice. overrideIndex.removeIfOverriddenBy(method, true, injectableMethod); } overrideIndex.add(injectableMethod); } } else { if(overrideIndex != null) { boolean removed = overrideIndex.removeIfOverriddenBy(method, false, null); if(removed) { logger.log(Level.WARNING, "Method: {0} is not annotated with @Inject but " + "is overriding a method that is annotated with @javax.inject.Inject. Because " + "it is not annotated with @Inject, the method will not be injected. " + "To fix this, annotate the method with @Inject.", method); } } } } } } if (injectableMembers.isEmpty()) { return Collections.emptySet(); } ImmutableSet.Builder builder = ImmutableSet.builder(); for (InjectableMember im = injectableMembers.head; im != null; im = im.next) { try { builder.add(im.toInjectionPoint()); } catch (ConfigurationException ignorable) { if (!im.optional) { errors.merge(ignorable.getErrorMessages()); } } } return builder.build(); } private static boolean isValidMethod(InjectableMethod injectableMethod, Errors errors) { boolean result = true; if (injectableMethod.jsr330) { Method method = injectableMethod.method; if (Modifier.isAbstract(method.getModifiers())) { errors.cannotInjectAbstractMethod(method); result = false; } if (method.getTypeParameters().length > 0) { errors.cannotInjectMethodWithTypeParameters(method); result = false; } } return result; } private static List> hierarchyFor(TypeLiteral type) { List> hierarchy = new ArrayList>(); TypeLiteral current = type; while (current.getRawType() != Object.class) { hierarchy.add(current); current = current.getSupertype(current.getRawType().getSuperclass()); } return hierarchy; } /** * Returns true if a overrides b. Assumes signatures of a and b are the same and a's declaring * class is a subclass of b's declaring class. */ private static boolean overrides(Method a, Method b) { // See JLS section 8.4.8.1 int modifiers = b.getModifiers(); if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) { return true; } if (Modifier.isPrivate(modifiers)) { return false; } // b must be package-private return a.getDeclaringClass().getPackage().equals(b.getDeclaringClass().getPackage()); } /** * A method signature. Used to handle method overridding. */ static class Signature { final String name; final Class[] parameterTypes; final int hash; Signature(Method method) { this.name = method.getName(); this.parameterTypes = method.getParameterTypes(); int h = name.hashCode(); h = h * 31 + parameterTypes.length; for (Class parameterType : parameterTypes) { h = h * 31 + parameterType.hashCode(); } this.hash = h; } @Override public int hashCode() { return this.hash; } @Override public boolean equals(Object o) { if (!(o instanceof Signature)) { return false; } Signature other = (Signature) o; if (!name.equals(other.name)) { return false; } if (parameterTypes.length != other.parameterTypes.length) { return false; } for (int i = 0; i < parameterTypes.length; i++) { if (parameterTypes[i] != other.parameterTypes[i]) { return false; } } return true; } } } guice-3.0/core/src/com/google/inject/spi/ConstructorBinding.java0000644000175000017500000000347511460132772024663 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; import java.lang.reflect.Method; import java.util.List; import java.util.Map; import java.util.Set; /** * A binding to the constructor of a concrete clss. To resolve injections, an instance is * instantiated by invoking the constructor. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface ConstructorBinding extends Binding, HasDependencies { /** * Gets the constructor this binding injects. */ InjectionPoint getConstructor(); /** * Returns all instance method and field injection points on {@code type}. * * @return a possibly empty set of injection points. The set has a specified iteration order. All * fields are returned and then all methods. Within the fields, supertype fields are returned * before subtype fields. Similarly, supertype methods are returned before subtype methods. */ Set getInjectableMembers(); /*if[AOP]*/ /** * Returns the interceptors applied to each method, in the order that they will be applied. * * @return a possibly empty map */ Map> getMethodInterceptors(); /*end[AOP]*/ }guice-3.0/core/src/com/google/inject/spi/Message.java0000644000175000017500000000733611460132772022427 0ustar drazzibdrazzib/** * Copyright (C) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import com.google.inject.internal.Errors; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Objects; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.internal.util.SourceProvider; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.List; /** * An error message and the context in which it occured. Messages are usually created internally by * Guice and its extensions. Messages can be created explicitly in a module using {@link * com.google.inject.Binder#addError(Throwable) addError()} statements: *

 *     try {
 *       bindPropertiesFromFile();
 *     } catch (IOException e) {
 *       addError(e);
 *     }
* * @author crazybob@google.com (Bob Lee) */ public final class Message implements Serializable, Element { private final String message; private final Throwable cause; private final List sources; /** * @since 2.0 */ public Message(List sources, String message, Throwable cause) { this.sources = ImmutableList.copyOf(sources); this.message = checkNotNull(message, "message"); this.cause = cause; } public Message(Object source, String message) { this(ImmutableList.of(source), message, null); } public Message(String message) { this(ImmutableList.of(), message, null); } public String getSource() { return sources.isEmpty() ? SourceProvider.UNKNOWN_SOURCE.toString() : Errors.convert(sources.get(sources.size() - 1)).toString(); } /** @since 2.0 */ public List getSources() { return sources; } /** * Gets the error message text. */ public String getMessage() { return message; } /** @since 2.0 */ public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } /** * Returns the throwable that caused this message, or {@code null} if this * message was not caused by a throwable. * * @since 2.0 */ public Throwable getCause() { return cause; } @Override public String toString() { return message; } @Override public int hashCode() { return message.hashCode(); } @Override public boolean equals(Object o) { if (!(o instanceof Message)) { return false; } Message e = (Message) o; return message.equals(e.message) && Objects.equal(cause, e.cause) && sources.equals(e.sources); } /** @since 2.0 */ public void applyTo(Binder binder) { binder.withSource(getSource()).addError(this); } /** * When serialized, we eagerly convert sources to strings. This hurts our formatting, but it * guarantees that the receiving end will be able to read the message. */ private Object writeReplace() throws ObjectStreamException { Object[] sourcesAsStrings = sources.toArray(); for (int i = 0; i < sourcesAsStrings.length; i++) { sourcesAsStrings[i] = Errors.convert(sourcesAsStrings[i]).toString(); } return new Message(ImmutableList.of(sourcesAsStrings), message, cause); } private static final long serialVersionUID = 0; }guice-3.0/core/src/com/google/inject/spi/Toolable.java0000644000175000017500000000207311460132772022575 0ustar drazzibdrazzibpackage com.google.inject.spi; import com.google.inject.Injector; import com.google.inject.Stage; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Instructs an {@link Injector} running in {@link Stage#TOOL} that a method should be injected. * This is typically useful for for extensions to Guice that perform additional validation in an * injected method or field. This only applies to objects that are already constructed when * bindings are created (ie., something bound using {@link * com.google.inject.binder.LinkedBindingBuilder#toProvider toProvider}, {@link * com.google.inject.binder.LinkedBindingBuilder#toInstance toInstance}, or {@link * com.google.inject.Binder#requestInjection requestInjection}. * * @author sberlin@gmail.com (Sam Berlin) * @since 3.0 */ @Target({ METHOD }) @Retention(RUNTIME) @Documented public @interface Toolable { } guice-3.0/core/src/com/google/inject/spi/DisableCircularProxiesOption.java0000644000175000017500000000250611501174544026627 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import static com.google.inject.internal.util.Preconditions.checkNotNull; /** * A request to disable circular proxies. * * @author sameb@google.com (Sam Berlin) * @since 3.0 */ public final class DisableCircularProxiesOption implements Element { private final Object source; DisableCircularProxiesOption(Object source) { this.source = checkNotNull(source, "source"); } public Object getSource() { return source; } public void applyTo(Binder binder) { binder.withSource(getSource()).disableCircularProxies(); } public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } } guice-3.0/core/src/com/google/inject/spi/TypeEncounter.java0000644000175000017500000001134711460132772023644 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Key; import com.google.inject.MembersInjector; import com.google.inject.Provider; import com.google.inject.TypeLiteral; import com.google.inject.matcher.Matcher; import java.lang.reflect.Method; /** * Context of an injectable type encounter. Enables reporting errors, registering injection * listeners and binding method interceptors for injectable type {@code I}. It is an error to use * an encounter after the {@link TypeListener#hear(TypeLiteral, TypeEncounter) hear()} method has * returned. * * @param the injectable type encountered * @since 2.0 */ public interface TypeEncounter { /** * Records an error message for type {@code I} which will be presented to the user at a later * time. Unlike throwing an exception, this enable us to continue configuring the Injector and * discover more errors. Uses {@link String#format(String, Object[])} to insert the arguments * into the message. */ void addError(String message, Object... arguments); /** * Records an exception for type {@code I}, the full details of which will be logged, and the * message of which will be presented to the user at a later time. If your type listener calls * something that you worry may fail, you should catch the exception and pass it to this method. */ void addError(Throwable t); /** * Records an error message to be presented to the user at a later time. */ void addError(Message message); /** * Returns the provider used to obtain instances for the given injection key. The returned * provider will not be valid until the injector has been created. The provider will throw an * {@code IllegalStateException} if you try to use it beforehand. */ Provider getProvider(Key key); /** * Returns the provider used to obtain instances for the given injection type. The returned * provider will not be valid until the injetor has been created. The provider will throw an * {@code IllegalStateException} if you try to use it beforehand. */ Provider getProvider(Class type); /** * Returns the members injector used to inject dependencies into methods and fields on instances * of the given type {@code T}. The returned members injector will not be valid until the main * injector has been created. The members injector will throw an {@code IllegalStateException} * if you try to use it beforehand. * * @param typeLiteral type to get members injector for */ MembersInjector getMembersInjector(TypeLiteral typeLiteral); /** * Returns the members injector used to inject dependencies into methods and fields on instances * of the given type {@code T}. The returned members injector will not be valid until the main * injector has been created. The members injector will throw an {@code IllegalStateException} * if you try to use it beforehand. * * @param type type to get members injector for */ MembersInjector getMembersInjector(Class type); /** * Registers a members injector for type {@code I}. Guice will use the members injector after its * performed its own injections on an instance of {@code I}. */ void register(MembersInjector membersInjector); /** * Registers an injection listener for type {@code I}. Guice will notify the listener after all * injections have been performed on an instance of {@code I}. */ void register(InjectionListener listener); /*if[AOP]*/ /** * Binds method interceptor[s] to methods matched in type {@code I} and its supertypes. A * method is eligible for interception if: * *
    *
  • Guice created the instance the method is on
  • *
  • Neither the enclosing type nor the method is final
  • *
  • And the method is package-private or more accessible
  • *
* * @param methodMatcher matches methods the interceptor should apply to. For * example: {@code annotatedWith(Transactional.class)}. * @param interceptors to bind */ void bindInterceptor(Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors); /*end[AOP]*/ } guice-3.0/core/src/com/google/inject/spi/MembersInjectorLookup.java0000644000175000017500000000641211460132772025317 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import com.google.inject.MembersInjector; import com.google.inject.TypeLiteral; import static com.google.inject.internal.util.Preconditions.checkNotNull; import static com.google.inject.internal.util.Preconditions.checkState; /** * A lookup of the members injector for a type. Lookups are created explicitly in a module using * {@link com.google.inject.Binder#getMembersInjector(Class) getMembersInjector()} statements: *
 *     MembersInjector<PaymentService> membersInjector
 *         = getMembersInjector(PaymentService.class);
* * @author crazybob@google.com (Bob Lee) * @since 2.0 */ public final class MembersInjectorLookup implements Element { private final Object source; private final TypeLiteral type; private MembersInjector delegate; public MembersInjectorLookup(Object source, TypeLiteral type) { this.source = checkNotNull(source, "source"); this.type = checkNotNull(type, "type"); } public Object getSource() { return source; } /** * Gets the type containing the members to be injected. */ public TypeLiteral getType() { return type; } public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } /** * Sets the actual members injector. * * @throws IllegalStateException if the delegate is already set */ public void initializeDelegate(MembersInjector delegate) { checkState(this.delegate == null, "delegate already initialized"); this.delegate = checkNotNull(delegate, "delegate"); } public void applyTo(Binder binder) { initializeDelegate(binder.withSource(getSource()).getMembersInjector(type)); } /** * Returns the delegate members injector, or {@code null} if it has not yet been initialized. * The delegate will be initialized when this element is processed, or otherwise used to create * an injector. */ public MembersInjector getDelegate() { return delegate; } /** * Returns the looked up members injector. The result is not valid until this lookup has been * initialized, which usually happens when the injector is created. The members injector will * throw an {@code IllegalStateException} if you try to use it beforehand. */ public MembersInjector getMembersInjector() { return new MembersInjector() { public void injectMembers(T instance) { checkState(delegate != null, "This MembersInjector cannot be used until the Injector has been created."); delegate.injectMembers(instance); } @Override public String toString() { return "MembersInjector<" + type + ">"; } }; } }guice-3.0/core/src/com/google/inject/spi/ProviderInstanceBinding.java0000644000175000017500000000243411460132772025607 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; import com.google.inject.Provider; import java.util.Set; /** * A binding to a provider instance. The provider's {@code get} method is invoked to resolve * injections. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface ProviderInstanceBinding extends Binding, HasDependencies { /** * Returns the user-supplied, unscoped provider. */ Provider getProviderInstance(); /** * Returns the field and method injection points of the provider, injected at injector-creation * time only. * * @return a possibly empty set */ Set getInjectionPoints(); }guice-3.0/core/src/com/google/inject/spi/PrivateElements.java0000644000175000017500000000362411460132772024146 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Injector; import com.google.inject.Key; import java.util.List; import java.util.Set; /** * A private collection of elements that are hidden from the enclosing injector or module by * default. See {@link com.google.inject.PrivateModule PrivateModule} for details. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface PrivateElements extends Element { /** * Returns the configuration information in this private environment. */ List getElements(); /** * Returns the child injector that hosts these private elements, or null if the elements haven't * been used to create an injector. */ Injector getInjector(); /** * Returns the unique exposed keys for these private elements. */ Set> getExposedKeys(); /** * Returns an arbitrary object containing information about the "place" where this key was * exposed. Used by Guice in the production of descriptive error messages. * *

Tools might specially handle types they know about; {@code StackTraceElement} is a good * example. Tools should simply call {@code toString()} on the source object if the type is * unfamiliar. * * @param key one of the keys exposed by this module. */ Object getExposedSource(Key key); } guice-3.0/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java0000644000175000017500000000463111460132772026444 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; /** * No-op visitor for subclassing. All interface methods simply delegate to {@link * #visitOther(Binding)}, returning its result. * * @param any type to be returned by the visit method. Use {@link Void} with * {@code return null} if no return type is needed. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public abstract class DefaultBindingTargetVisitor implements BindingTargetVisitor { /** * Default visit implementation. Returns {@code null}. */ protected V visitOther(Binding binding) { return null; } public V visit(InstanceBinding instanceBinding) { return visitOther(instanceBinding); } public V visit(ProviderInstanceBinding providerInstanceBinding) { return visitOther(providerInstanceBinding); } public V visit(ProviderKeyBinding providerKeyBinding) { return visitOther(providerKeyBinding); } public V visit(LinkedKeyBinding linkedKeyBinding) { return visitOther(linkedKeyBinding); } public V visit(ExposedBinding exposedBinding) { return visitOther(exposedBinding); } public V visit(UntargettedBinding untargettedBinding) { return visitOther(untargettedBinding); } public V visit(ConstructorBinding constructorBinding) { return visitOther(constructorBinding); } public V visit(ConvertedConstantBinding convertedConstantBinding) { return visitOther(convertedConstantBinding); } // javac says it's an error to cast ProviderBinding to Binding @SuppressWarnings("unchecked") public V visit(ProviderBinding providerBinding) { return visitOther((Binding) providerBinding); } } guice-3.0/core/src/com/google/inject/spi/HasDependencies.java0000644000175000017500000000234311460132772024056 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import java.util.Set; /** * Implemented by {@link com.google.inject.Binding bindings}, {@link com.google.inject.Provider * providers} and instances that expose their dependencies explicitly. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface HasDependencies { /** * Returns the known dependencies for this type. If this has dependencies whose values are not * known statically, a dependency for the {@link com.google.inject.Injector Injector} will be * included in the returned set. * * @return a possibly empty set */ Set> getDependencies(); } guice-3.0/core/src/com/google/inject/spi/TypeConverter.java0000644000175000017500000000171411460132772023646 0ustar drazzibdrazzib/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.TypeLiteral; /** * Converts constant string values to a different type. * * @author crazybob@google.com (Bob Lee) * @since 2.0 */ public interface TypeConverter { /** * Converts a string value. Throws an exception if a conversion error occurs. */ Object convert(String value, TypeLiteral toType); } guice-3.0/core/src/com/google/inject/spi/InstanceBinding.java0000644000175000017500000000226611460132772024077 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; import java.util.Set; /** * A binding to a single instance. The same instance is returned for every injection. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface InstanceBinding extends Binding, HasDependencies { /** * Returns the user-supplied instance. */ T getInstance(); /** * Returns the field and method injection points of the instance, injected at injector-creation * time only. * * @return a possibly empty set */ Set getInjectionPoints(); } guice-3.0/core/src/com/google/inject/spi/Element.java0000644000175000017500000000437211460132772022431 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; /** * A core component of a module or injector. * *

The elements of a module can be inspected, validated and rewritten. Use {@link * Elements#getElements(com.google.inject.Module[]) Elements.getElements()} to read the elements * from a module, and {@link Elements#getModule(Iterable) Elements.getModule()} to rewrite them. * This can be used for static analysis and generation of Guice modules. * *

The elements of an injector can be inspected and exercised. Use {@link * com.google.inject.Injector#getBindings Injector.getBindings()} to reflect on Guice injectors. * * @author jessewilson@google.com (Jesse Wilson) * @author crazybob@google.com (Bob Lee) * @since 2.0 */ public interface Element { /** * Returns an arbitrary object containing information about the "place" where this element was * configured. Used by Guice in the production of descriptive error messages. * *

Tools might specially handle types they know about; {@code StackTraceElement} is a good * example. Tools should simply call {@code toString()} on the source object if the type is * unfamiliar. */ Object getSource(); /** * Accepts an element visitor. Invokes the visitor method specific to this element's type. * * @param visitor to call back on */ T acceptVisitor(ElementVisitor visitor); /** * Writes this module element to the given binder (optional operation). * * @param binder to apply configuration element to * @throws UnsupportedOperationException if the {@code applyTo} method is not supported by this * element. */ void applyTo(Binder binder); } guice-3.0/core/src/com/google/inject/spi/InjectionRequest.java0000644000175000017500000000550111460132772024326 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import com.google.inject.ConfigurationException; import com.google.inject.TypeLiteral; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.util.Set; /** * A request to inject the instance fields and methods of an instance. Requests are created * explicitly in a module using {@link com.google.inject.Binder#requestInjection(Object) * requestInjection()} statements: *

 *     requestInjection(serviceInstance);
* * @author mikeward@google.com (Mike Ward) * @since 2.0 */ public final class InjectionRequest implements Element { private final Object source; private final TypeLiteral type; private final T instance; public InjectionRequest(Object source, TypeLiteral type, T instance) { this.source = checkNotNull(source, "source"); this.type = checkNotNull(type, "type"); this.instance = checkNotNull(instance, "instance"); } public Object getSource() { return source; } public T getInstance() { return instance; } public TypeLiteral getType() { return type; } /** * Returns the instance methods and fields of {@code instance} that will be injected to fulfill * this request. * * @return a possibly empty set of injection points. The set has a specified iteration order. All * fields are returned and then all methods. Within the fields, supertype fields are returned * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on the class of {@code * instance}, such as a field with multiple binding annotations. The exception's {@link * ConfigurationException#getPartialValue() partial value} is a {@code Set} * of the valid injection points. */ public Set getInjectionPoints() throws ConfigurationException { return InjectionPoint.forInstanceMethodsAndFields(instance.getClass()); } public R acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } public void applyTo(Binder binder) { binder.withSource(getSource()).requestInjection(type, instance); } } guice-3.0/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java0000644000175000017500000000251211501174514027013 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import static com.google.inject.internal.util.Preconditions.checkNotNull; /** * A request to require explicit bindings. * * @author sameb@google.com (Sam Berlin) * @since 3.0 */ public final class RequireExplicitBindingsOption implements Element { private final Object source; RequireExplicitBindingsOption(Object source) { this.source = checkNotNull(source, "source"); } public Object getSource() { return source; } public void applyTo(Binder binder) { binder.withSource(getSource()).requireExplicitBindings(); } public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } } guice-3.0/core/src/com/google/inject/spi/ConvertedConstantBinding.java0000644000175000017500000000305011471307724025771 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; import com.google.inject.Key; import java.util.Set; /** * A binding created from converting a bound instance to a new type. The source binding has the same * binding annotation but a different type. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface ConvertedConstantBinding extends Binding, HasDependencies { /** * Returns the converted value. */ T getValue(); /** * Returns the type converter binding used to convert the constant. * * @since 3.0 */ TypeConverterBinding getTypeConverterBinding(); /** * Returns the key for the source binding. That binding can e retrieved from an injector using * {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}. */ Key getSourceKey(); /** * Returns a singleton set containing only the converted key. */ Set> getDependencies(); }guice-3.0/core/src/com/google/inject/spi/ExposedBinding.java0000644000175000017500000000220011460132772023726 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import com.google.inject.Binding; /** * A binding to a key exposed from an enclosed private environment. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface ExposedBinding extends Binding, HasDependencies { /** * Returns the enclosed environment that holds the original binding. */ PrivateElements getPrivateElements(); /** * Unsupported. Always throws {@link UnsupportedOperationException}. */ void applyTo(Binder binder); }guice-3.0/core/src/com/google/inject/spi/UntargettedBinding.java0000644000175000017500000000165011460132772024615 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; /** * An untargetted binding. This binding indicates that the injector should use its implicit binding * strategies to resolve injections. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface UntargettedBinding extends Binding {} guice-3.0/core/src/com/google/inject/spi/ProviderLookup.java0000644000175000017500000000577411460132772024033 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.Provider; import static com.google.inject.internal.util.Preconditions.checkNotNull; import static com.google.inject.internal.util.Preconditions.checkState; /** * A lookup of the provider for a type. Lookups are created explicitly in a module using * {@link com.google.inject.Binder#getProvider(Class) getProvider()} statements: *
 *     Provider<PaymentService> paymentServiceProvider
 *         = getProvider(PaymentService.class);
* * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class ProviderLookup implements Element { private final Object source; private final Key key; private Provider delegate; public ProviderLookup(Object source, Key key) { this.source = checkNotNull(source, "source"); this.key = checkNotNull(key, "key"); } public Object getSource() { return source; } public Key getKey() { return key; } public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } /** * Sets the actual provider. * * @throws IllegalStateException if the delegate is already set */ public void initializeDelegate(Provider delegate) { checkState(this.delegate == null, "delegate already initialized"); this.delegate = checkNotNull(delegate, "delegate"); } public void applyTo(Binder binder) { initializeDelegate(binder.withSource(getSource()).getProvider(key)); } /** * Returns the delegate provider, or {@code null} if it has not yet been initialized. The delegate * will be initialized when this element is processed, or otherwise used to create an injector. */ public Provider getDelegate() { return delegate; } /** * Returns the looked up provider. The result is not valid until this lookup has been initialized, * which usually happens when the injector is created. The provider will throw an {@code * IllegalStateException} if you try to use it beforehand. */ public Provider getProvider() { return new Provider() { public T get() { checkState(delegate != null, "This Provider cannot be used until the Injector has been created."); return delegate.get(); } @Override public String toString() { return "Provider<" + key.getTypeLiteral() + ">"; } }; } } guice-3.0/core/src/com/google/inject/spi/InjectionListener.java0000644000175000017500000000214711460132772024466 0ustar drazzibdrazzib/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; /** * Listens for injections into instances of type {@code I}. Useful for performing further * injections, post-injection initialization, and more. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface InjectionListener { /** * Invoked by Guice after it injects the fields and methods of instance. * * @param injectee instance that Guice injected dependencies into */ void afterInjection(I injectee); } guice-3.0/core/src/com/google/inject/spi/DefaultBindingScopingVisitor.java0000644000175000017500000000301211460132772026610 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Scope; import java.lang.annotation.Annotation; /** * No-op visitor for subclassing. All interface methods simply delegate to * {@link #visitOther()}, returning its result. * * @param any type to be returned by the visit method. Use {@link Void} with * {@code return null} if no return type is needed. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public class DefaultBindingScopingVisitor implements BindingScopingVisitor { /** * Default visit implementation. Returns {@code null}. */ protected V visitOther() { return null; } public V visitEagerSingleton() { return visitOther(); } public V visitScope(Scope scope) { return visitOther(); } public V visitScopeAnnotation(Class scopeAnnotation) { return visitOther(); } public V visitNoScoping() { return visitOther(); } } guice-3.0/core/src/com/google/inject/spi/Elements.java0000644000175000017500000002727611531414136022620 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.AbstractModule; import com.google.inject.Binder; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.MembersInjector; import com.google.inject.Module; import com.google.inject.PrivateBinder; import com.google.inject.PrivateModule; import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.Stage; import com.google.inject.TypeLiteral; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.binder.AnnotatedConstantBindingBuilder; import com.google.inject.binder.AnnotatedElementBuilder; import com.google.inject.internal.AbstractBindingBuilder; import com.google.inject.internal.BindingBuilder; import com.google.inject.internal.ConstantBindingBuilderImpl; import com.google.inject.internal.Errors; import com.google.inject.internal.ExposureBuilder; import com.google.inject.internal.PrivateElementsImpl; import com.google.inject.internal.ProviderMethodsModule; import com.google.inject.internal.util.ImmutableList; import com.google.inject.internal.util.Lists; import static com.google.inject.internal.util.Preconditions.checkArgument; import com.google.inject.internal.util.Sets; import com.google.inject.internal.util.SourceProvider; import com.google.inject.matcher.Matcher; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; /** * Exposes elements of a module so they can be inspected, validated or {@link * Element#applyTo(Binder) rewritten}. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class Elements { private static final BindingTargetVisitor GET_INSTANCE_VISITOR = new DefaultBindingTargetVisitor() { @Override public Object visit(InstanceBinding binding) { return binding.getInstance(); } @Override protected Object visitOther(Binding binding) { throw new IllegalArgumentException(); } }; /** * Records the elements executed by {@code modules}. */ public static List getElements(Module... modules) { return getElements(Stage.DEVELOPMENT, Arrays.asList(modules)); } /** * Records the elements executed by {@code modules}. */ public static List getElements(Stage stage, Module... modules) { return getElements(stage, Arrays.asList(modules)); } /** * Records the elements executed by {@code modules}. */ public static List getElements(Iterable modules) { return getElements(Stage.DEVELOPMENT, modules); } /** * Records the elements executed by {@code modules}. */ public static List getElements(Stage stage, Iterable modules) { RecordingBinder binder = new RecordingBinder(stage); for (Module module : modules) { binder.install(module); } return Collections.unmodifiableList(binder.elements); } /** * Returns the module composed of {@code elements}. */ public static Module getModule(final Iterable elements) { return new Module() { public void configure(Binder binder) { for (Element element : elements) { element.applyTo(binder); } } }; } @SuppressWarnings("unchecked") static BindingTargetVisitor getInstanceVisitor() { return (BindingTargetVisitor) GET_INSTANCE_VISITOR; } private static class RecordingBinder implements Binder, PrivateBinder { private final Stage stage; private final Set modules; private final List elements; private final Object source; private final SourceProvider sourceProvider; /** The binder where exposed bindings will be created */ private final RecordingBinder parent; private final PrivateElementsImpl privateElements; private RecordingBinder(Stage stage) { this.stage = stage; this.modules = Sets.newHashSet(); this.elements = Lists.newArrayList(); this.source = null; this.sourceProvider = SourceProvider.DEFAULT_INSTANCE.plusSkippedClasses( Elements.class, RecordingBinder.class, AbstractModule.class, ConstantBindingBuilderImpl.class, AbstractBindingBuilder.class, BindingBuilder.class); this.parent = null; this.privateElements = null; } /** Creates a recording binder that's backed by {@code prototype}. */ private RecordingBinder( RecordingBinder prototype, Object source, SourceProvider sourceProvider) { checkArgument(source == null ^ sourceProvider == null); this.stage = prototype.stage; this.modules = prototype.modules; this.elements = prototype.elements; this.source = source; this.sourceProvider = sourceProvider; this.parent = prototype.parent; this.privateElements = prototype.privateElements; } /** Creates a private recording binder. */ private RecordingBinder(RecordingBinder parent, PrivateElementsImpl privateElements) { this.stage = parent.stage; this.modules = Sets.newHashSet(); this.elements = privateElements.getElementsMutable(); this.source = parent.source; this.sourceProvider = parent.sourceProvider; this.parent = parent; this.privateElements = privateElements; } /*if[AOP]*/ public void bindInterceptor( Matcher> classMatcher, Matcher methodMatcher, org.aopalliance.intercept.MethodInterceptor... interceptors) { elements.add(new InterceptorBinding(getSource(), classMatcher, methodMatcher, interceptors)); } /*end[AOP]*/ public void bindScope(Class annotationType, Scope scope) { elements.add(new ScopeBinding(getSource(), annotationType, scope)); } @SuppressWarnings("unchecked") // it is safe to use the type literal for the raw type public void requestInjection(Object instance) { requestInjection((TypeLiteral) TypeLiteral.get(instance.getClass()), instance); } public void requestInjection(TypeLiteral type, T instance) { elements.add(new InjectionRequest(getSource(), type, instance)); } public MembersInjector getMembersInjector(final TypeLiteral typeLiteral) { final MembersInjectorLookup element = new MembersInjectorLookup(getSource(), typeLiteral); elements.add(element); return element.getMembersInjector(); } public MembersInjector getMembersInjector(Class type) { return getMembersInjector(TypeLiteral.get(type)); } public void bindListener(Matcher> typeMatcher, TypeListener listener) { elements.add(new TypeListenerBinding(getSource(), listener, typeMatcher)); } public void requestStaticInjection(Class... types) { for (Class type : types) { elements.add(new StaticInjectionRequest(getSource(), type)); } } public void install(Module module) { if (modules.add(module)) { Binder binder = this; if (module instanceof PrivateModule) { binder = binder.newPrivateBinder(); } try { module.configure(binder); } catch (RuntimeException e) { Collection messages = Errors.getMessagesFromThrowable(e); if (!messages.isEmpty()) { elements.addAll(messages); } else { addError(e); } } binder.install(ProviderMethodsModule.forModule(module)); } } public Stage currentStage() { return stage; } public void addError(String message, Object... arguments) { elements.add(new Message(getSource(), Errors.format(message, arguments))); } public void addError(Throwable t) { String message = "An exception was caught and reported. Message: " + t.getMessage(); elements.add(new Message(ImmutableList.of(getSource()), message, t)); } public void addError(Message message) { elements.add(message); } public AnnotatedBindingBuilder bind(Key key) { return new BindingBuilder(this, elements, getSource(), key); } public AnnotatedBindingBuilder bind(TypeLiteral typeLiteral) { return bind(Key.get(typeLiteral)); } public AnnotatedBindingBuilder bind(Class type) { return bind(Key.get(type)); } public AnnotatedConstantBindingBuilder bindConstant() { return new ConstantBindingBuilderImpl(this, elements, getSource()); } public Provider getProvider(final Key key) { final ProviderLookup element = new ProviderLookup(getSource(), key); elements.add(element); return element.getProvider(); } public Provider getProvider(Class type) { return getProvider(Key.get(type)); } public void convertToTypes(Matcher> typeMatcher, TypeConverter converter) { elements.add(new TypeConverterBinding(getSource(), typeMatcher, converter)); } public RecordingBinder withSource(final Object source) { return new RecordingBinder(this, source, null); } public RecordingBinder skipSources(Class... classesToSkip) { // if a source is specified explicitly, we don't need to skip sources if (source != null) { return this; } SourceProvider newSourceProvider = sourceProvider.plusSkippedClasses(classesToSkip); return new RecordingBinder(this, null, newSourceProvider); } public PrivateBinder newPrivateBinder() { PrivateElementsImpl privateElements = new PrivateElementsImpl(getSource()); elements.add(privateElements); return new RecordingBinder(this, privateElements); } public void disableCircularProxies() { elements.add(new DisableCircularProxiesOption(getSource())); } public void requireExplicitBindings() { elements.add(new RequireExplicitBindingsOption(getSource())); } public void expose(Key key) { exposeInternal(key); } public AnnotatedElementBuilder expose(Class type) { return exposeInternal(Key.get(type)); } public AnnotatedElementBuilder expose(TypeLiteral type) { return exposeInternal(Key.get(type)); } private AnnotatedElementBuilder exposeInternal(Key key) { if (privateElements == null) { addError("Cannot expose %s on a standard binder. " + "Exposed bindings are only applicable to private binders.", key); return new AnnotatedElementBuilder() { public void annotatedWith(Class annotationType) {} public void annotatedWith(Annotation annotation) {} }; } ExposureBuilder builder = new ExposureBuilder(this, getSource(), key); privateElements.addExposureBuilder(builder); return builder; } protected Object getSource() { return sourceProvider != null ? sourceProvider.get() : source; } @Override public String toString() { return "Binder"; } } } guice-3.0/core/src/com/google/inject/spi/TypeConverterBinding.java0000644000175000017500000000444311471307704025144 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import com.google.inject.TypeLiteral; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.matcher.Matcher; /** * Registration of type converters for matching target types. Instances are created * explicitly in a module using {@link com.google.inject.Binder#convertToTypes(Matcher, * TypeConverter) convertToTypes()} statements: *
 *     convertToTypes(Matchers.only(TypeLiteral.get(DateTime.class)), new DateTimeConverter());
* * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class TypeConverterBinding implements Element { private final Object source; private final Matcher> typeMatcher; private final TypeConverter typeConverter; /** @since 3.0 */ public TypeConverterBinding(Object source, Matcher> typeMatcher, TypeConverter typeConverter) { this.source = checkNotNull(source, "source"); this.typeMatcher = checkNotNull(typeMatcher, "typeMatcher"); this.typeConverter = checkNotNull(typeConverter, "typeConverter"); } public Object getSource() { return source; } public Matcher> getTypeMatcher() { return typeMatcher; } public TypeConverter getTypeConverter() { return typeConverter; } public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } public void applyTo(Binder binder) { binder.withSource(getSource()).convertToTypes(typeMatcher, typeConverter); } @Override public String toString() { return typeConverter + " which matches " + typeMatcher + " (bound at " + source + ")"; } } guice-3.0/core/src/com/google/inject/spi/TypeListener.java0000644000175000017500000000336711471763220023472 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.TypeLiteral; /** * Listens for Guice to encounter injectable types. If a given type has its constructor injected in * one situation but only its methods and fields injected in another, Guice will notify this * listener once. * *

Useful for extra type checking, {@linkplain TypeEncounter#register(InjectionListener) * registering injection listeners}, and {@linkplain TypeEncounter#bindInterceptor( * com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[]) * binding method interceptors}. * * @since 2.0 */ public interface TypeListener { /** * Invoked when Guice encounters a new type eligible for constructor or members injection. * Called during injector creation (or afterwords if Guice encounters a type at run time and * creates a JIT binding). * * @param type encountered by Guice * @param encounter context of this encounter, enables reporting errors, registering injection * listeners and binding method interceptors for {@code type}. * * @param the injectable type */ void hear(TypeLiteral type, TypeEncounter encounter); } guice-3.0/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java0000644000175000017500000000465111463267552026753 0ustar drazzibdrazzib/** * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; import com.google.inject.Provider; /** * A Provider that is part of an extension which supports a custom * BindingTargetVisitor. *

* When an extension binds a provider instance, the provider can implement this * interface to allow users using the * {@link Binding#acceptTargetVisitor(BindingTargetVisitor)} method to visit a * custom visitor designed for that extension. A typical implementation within * the extension would look like *

 
 * <V, B> V acceptExtensionVisitor(BindingTargetVisitor<B, V> visitor, ProviderInstanceBinding<? extends B> binding) {
 *   if(visitor instanceof MyCustomExtensionVisitor) {
 *     return ((MyCustomExtensionVisitor<B, V>)visitor).visitCustomExtension(customProperties, binding);
 *   } else {
 *     return visitor.visit(binding);
 *   }
 * }
* 'MyCustomExtensionVisitor' in the example above would be an interface the * extension provides that users can implement in order to be notified of custom * extension information. These visitor interfaces must extend from * BindingTargetVisitor. * * @since 3.0 * @author sameb@google.com (Sam Berlin) */ public interface ProviderWithExtensionVisitor extends Provider { /** * Instructs the extension determine if the visitor is an instance of a custom * extension visitor, and if so, visit it using that method. If the visitor is * not an instance of the custom extension visitor, this method MUST * call visitor.visit(binding). *

* Due to issues with generics, the type parameters of this method do not * relate to the type of the provider. In practice, the 'B' type will always * be a supertype of 'T'. */ V acceptExtensionVisitor(BindingTargetVisitor visitor, ProviderInstanceBinding binding); } guice-3.0/core/src/com/google/inject/spi/BindingTargetVisitor.java0000644000175000017500000000575111460132772025143 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; /** * Visits each of the strategies used to find an instance to satisfy an injection. * * @param any type to be returned by the visit method. Use {@link Void} with * {@code return null} if no return type is needed. * @since 2.0 */ public interface BindingTargetVisitor { /** * Visit a instance binding. The same instance is returned for every injection. This target is * found in both module and injector bindings. */ V visit(InstanceBinding binding); /** * Visit a provider instance binding. The provider's {@code get} method is invoked to resolve * injections. This target is found in both module and injector bindings. */ V visit(ProviderInstanceBinding binding); /** * Visit a provider key binding. To resolve injections, the provider key is first resolved, then * that provider's {@code get} method is invoked. This target is found in both module and injector * bindings. */ V visit(ProviderKeyBinding binding); /** * Visit a linked key binding. The other key's binding is used to resolve injections. This * target is found in both module and injector bindings. */ V visit(LinkedKeyBinding binding); /** * Visit a binding to a key exposed from an enclosed private environment. This target is only * found in injector bindings. */ V visit(ExposedBinding binding); /** * Visit an untargetted binding. This target is found only on module bindings. It indicates * that the injector should use its implicit binding strategies to resolve injections. */ V visit(UntargettedBinding binding); /** * Visit a constructor binding. To resolve injections, an instance is instantiated by invoking * {@code constructor}. This target is found only on injector bindings. */ V visit(ConstructorBinding binding); /** * Visit a binding created from converting a bound instance to a new type. The source binding * has the same binding annotation but a different type. This target is found only on injector * bindings. */ V visit(ConvertedConstantBinding binding); /** * Visit a binding to a {@link com.google.inject.Provider} that delegates to the binding for the * provided type. This target is found only on injector bindings. */ V visit(ProviderBinding binding); } guice-3.0/core/src/com/google/inject/spi/InterceptorBinding.java0000644000175000017500000000554111460132772024630 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import com.google.inject.internal.util.ImmutableList; import static com.google.inject.internal.util.Preconditions.checkNotNull; import com.google.inject.matcher.Matcher; import java.lang.reflect.Method; import java.util.List; import org.aopalliance.intercept.MethodInterceptor; /** * Registration of interceptors for matching methods of matching classes. Instances are created * explicitly in a module using {@link com.google.inject.Binder#bindInterceptor( * Matcher, Matcher, MethodInterceptor[]) bindInterceptor()} statements: *

 *     bindInterceptor(Matchers.subclassesOf(MyAction.class),
 *         Matchers.annotatedWith(Transactional.class),
 *         new MyTransactionInterceptor());
* * or from an injectable type listener using {@link TypeEncounter#bindInterceptor(Matcher, * org.aopalliance.intercept.MethodInterceptor[]) TypeEncounter.bindInterceptor()}. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class InterceptorBinding implements Element { private final Object source; private final Matcher> classMatcher; private final Matcher methodMatcher; private final ImmutableList interceptors; InterceptorBinding( Object source, Matcher> classMatcher, Matcher methodMatcher, MethodInterceptor[] interceptors) { this.source = checkNotNull(source, "source"); this.classMatcher = checkNotNull(classMatcher, "classMatcher"); this.methodMatcher = checkNotNull(methodMatcher, "methodMatcher"); this.interceptors = ImmutableList.of(interceptors); } public Object getSource() { return source; } public Matcher> getClassMatcher() { return classMatcher; } public Matcher getMethodMatcher() { return methodMatcher; } public List getInterceptors() { return interceptors; } public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } public void applyTo(Binder binder) { binder.withSource(getSource()).bindInterceptor(classMatcher, methodMatcher, interceptors.toArray(new MethodInterceptor[interceptors.size()])); } } guice-3.0/core/src/com/google/inject/spi/DefaultElementVisitor.java0000644000175000017500000000467111531414136025314 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; /** * No-op visitor for subclassing. All interface methods simply delegate to * {@link #visitOther(Element)}, returning its result. * * @param any type to be returned by the visit method. Use {@link Void} with * {@code return null} if no return type is needed. * * @author sberlin@gmail.com (Sam Berlin) * @since 2.0 */ public abstract class DefaultElementVisitor implements ElementVisitor { /** * Default visit implementation. Returns {@code null}. */ protected V visitOther(Element element) { return null; } public V visit(Message message) { return visitOther(message); } public V visit(Binding binding) { return visitOther(binding); } /*if[AOP]*/ public V visit(InterceptorBinding interceptorBinding) { return visitOther(interceptorBinding); } /*end[AOP]*/ public V visit(ScopeBinding scopeBinding) { return visitOther(scopeBinding); } public V visit(TypeConverterBinding typeConverterBinding) { return visitOther(typeConverterBinding); } public V visit(ProviderLookup providerLookup) { return visitOther(providerLookup); } public V visit(InjectionRequest injectionRequest) { return visitOther(injectionRequest); } public V visit(StaticInjectionRequest staticInjectionRequest) { return visitOther(staticInjectionRequest); } public V visit(PrivateElements privateElements) { return visitOther(privateElements); } public V visit(MembersInjectorLookup lookup) { return visitOther(lookup); } public V visit(TypeListenerBinding binding) { return visitOther(binding); } public V visit(DisableCircularProxiesOption option) { return visitOther(option); } public V visit(RequireExplicitBindingsOption option) { return visitOther(option); } } guice-3.0/core/src/com/google/inject/spi/StaticInjectionRequest.java0000644000175000017500000000514111460132772025476 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import com.google.inject.ConfigurationException; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.util.Set; /** * A request to inject the static fields and methods of a type. Requests are created * explicitly in a module using {@link com.google.inject.Binder#requestStaticInjection(Class[]) * requestStaticInjection()} statements: *
 *     requestStaticInjection(MyLegacyService.class);
* * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class StaticInjectionRequest implements Element { private final Object source; private final Class type; StaticInjectionRequest(Object source, Class type) { this.source = checkNotNull(source, "source"); this.type = checkNotNull(type, "type"); } public Object getSource() { return source; } public Class getType() { return type; } /** * Returns the static methods and fields of {@code type} that will be injected to fulfill this * request. * * @return a possibly empty set of injection points. The set has a specified iteration order. All * fields are returned and then all methods. Within the fields, supertype fields are returned * before subtype fields. Similarly, supertype methods are returned before subtype methods. * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as * a field with multiple binding annotations. The exception's {@link * ConfigurationException#getPartialValue() partial value} is a {@code Set} * of the valid injection points. */ public Set getInjectionPoints() throws ConfigurationException { return InjectionPoint.forStaticMethodsAndFields(type); } public void applyTo(Binder binder) { binder.withSource(getSource()).requestStaticInjection(type); } public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } } guice-3.0/core/src/com/google/inject/spi/ElementVisitor.java0000644000175000017500000000503211531414136023777 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; /** * Visit elements. * * @param any type to be returned by the visit method. Use {@link Void} with * {@code return null} if no return type is needed. * * @since 2.0 */ public interface ElementVisitor { /** * Visit a mapping from a key (type and optional annotation) to the strategy for getting * instances of the type. */ V visit(Binding binding); /*if[AOP]*/ /** * Visit a registration of interceptors for matching methods of matching classes. */ V visit(InterceptorBinding binding); /*end[AOP]*/ /** * Visit a registration of a scope annotation with the scope that implements it. */ V visit(ScopeBinding binding); /** * Visit a registration of type converters for matching target types. */ V visit(TypeConverterBinding binding); /** * Visit a request to inject the instance fields and methods of an instance. */ V visit(InjectionRequest request); /** * Visit a request to inject the static fields and methods of type. */ V visit(StaticInjectionRequest request); /** * Visit a lookup of the provider for a type. */ V visit(ProviderLookup lookup); /** * Visit a lookup of the members injector. */ V visit(MembersInjectorLookup lookup); /** * Visit an error message and the context in which it occured. */ V visit(Message message); /** * Visit a collection of configuration elements for a {@linkplain com.google.inject.PrivateBinder * private binder}. */ V visit(PrivateElements elements); /** * Visit an injectable type listener binding. */ V visit(TypeListenerBinding binding); /** * Visit a require explicit bindings command. * * @since 3.0 */ V visit(RequireExplicitBindingsOption option); /** * Visit a disable circular proxies command. * * @since 3.0 */ V visit(DisableCircularProxiesOption option); } guice-3.0/core/src/com/google/inject/spi/ScopeBinding.java0000644000175000017500000000401011460132772023371 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import com.google.inject.Scope; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.lang.annotation.Annotation; /** * Registration of a scope annotation with the scope that implements it. Instances are created * explicitly in a module using {@link com.google.inject.Binder#bindScope(Class, Scope) bindScope()} * statements: *
 *     Scope recordScope = new RecordScope();
 *     bindScope(RecordScoped.class, new RecordScope());
* * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class ScopeBinding implements Element { private final Object source; private final Class annotationType; private final Scope scope; ScopeBinding(Object source, Class annotationType, Scope scope) { this.source = checkNotNull(source, "source"); this.annotationType = checkNotNull(annotationType, "annotationType"); this.scope = checkNotNull(scope, "scope"); } public Object getSource() { return source; } public Class getAnnotationType() { return annotationType; } public Scope getScope() { return scope; } public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } public void applyTo(Binder binder) { binder.withSource(getSource()).bindScope(annotationType, scope); } } guice-3.0/core/src/com/google/inject/spi/Dependency.java0000644000175000017500000000757011460132772023121 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Key; import com.google.inject.internal.util.ImmutableSet; import com.google.inject.internal.util.Lists; import com.google.inject.internal.util.Objects; import static com.google.inject.internal.util.Preconditions.checkNotNull; import java.util.List; import java.util.Set; /** * A variable that can be resolved by an injector. * *

Use {@link #get} to build a freestanding dependency, or {@link InjectionPoint} to build one * that's attached to a constructor, method or field. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class Dependency { private final InjectionPoint injectionPoint; private final Key key; private final boolean nullable; private final int parameterIndex; Dependency(InjectionPoint injectionPoint, Key key, boolean nullable, int parameterIndex) { this.injectionPoint = injectionPoint; this.key = checkNotNull(key, "key"); this.nullable = nullable; this.parameterIndex = parameterIndex; } /** * Returns a new dependency that is not attached to an injection point. The returned dependency is * nullable. */ public static Dependency get(Key key) { return new Dependency(null, key, true, -1); } /** * Returns the dependencies from the given injection points. */ public static Set> forInjectionPoints(Set injectionPoints) { List> dependencies = Lists.newArrayList(); for (InjectionPoint injectionPoint : injectionPoints) { dependencies.addAll(injectionPoint.getDependencies()); } return ImmutableSet.copyOf(dependencies); } /** * Returns the key to the binding that satisfies this dependency. */ public Key getKey() { return this.key; } /** * Returns true if null is a legal value for this dependency. */ public boolean isNullable() { return nullable; } /** * Returns the injection point to which this dependency belongs, or null if this dependency isn't * attached to a particular injection point. */ public InjectionPoint getInjectionPoint() { return injectionPoint; } /** * Returns the index of this dependency in the injection point's parameter list, or {@code -1} if * this dependency does not belong to a parameter list. Only method and constuctor dependencies * are elements in a parameter list. */ public int getParameterIndex() { return parameterIndex; } @Override public int hashCode() { return Objects.hashCode(injectionPoint, parameterIndex, key); } @Override public boolean equals(Object o) { if (o instanceof Dependency) { Dependency dependency = (Dependency) o; return Objects.equal(injectionPoint, dependency.injectionPoint) && Objects.equal(parameterIndex, dependency.parameterIndex) && Objects.equal(key, dependency.key); } else { return false; } } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append(key); if (injectionPoint != null) { builder.append("@").append(injectionPoint); if (parameterIndex != -1) { builder.append("[").append(parameterIndex).append("]"); } } return builder.toString(); } } guice-3.0/core/src/com/google/inject/spi/LinkedKeyBinding.java0000644000175000017500000000220011460132772024176 0ustar drazzibdrazzib/** * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binding; import com.google.inject.Key; /** * A binding to a linked key. The other key's binding is used to resolve injections. * * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public interface LinkedKeyBinding extends Binding { /** * Returns the linked key used to resolve injections. That binding can be retrieved from an * injector using {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(key)}. */ Key getLinkedKey(); }guice-3.0/core/src/com/google/inject/spi/TypeListenerBinding.java0000644000175000017500000000404411460132772024756 0ustar drazzibdrazzib/** * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.inject.spi; import com.google.inject.Binder; import com.google.inject.TypeLiteral; import com.google.inject.matcher.Matcher; /** * Binds types (picked using a Matcher) to an type listener. Registrations are created explicitly in * a module using {@link com.google.inject.Binder#bindListener(Matcher, TypeListener)} statements: * *

 *     register(only(new TypeLiteral<PaymentService<CreditCard>>() {}), listener);
* * @author jessewilson@google.com (Jesse Wilson) * @since 2.0 */ public final class TypeListenerBinding implements Element { private final Object source; private final Matcher> typeMatcher; private final TypeListener listener; TypeListenerBinding(Object source, TypeListener listener, Matcher> typeMatcher) { this.source = source; this.listener = listener; this.typeMatcher = typeMatcher; } /** Returns the registered listener. */ public TypeListener getListener() { return listener; } /** Returns the type matcher which chooses which types the listener should be notified of. */ public Matcher> getTypeMatcher() { return typeMatcher; } public Object getSource() { return source; } public T acceptVisitor(ElementVisitor visitor) { return visitor.visit(this); } public void applyTo(Binder binder) { binder.withSource(getSource()).bindListener(typeMatcher, listener); } } guice-3.0/build.xml0000644000175000017500000002703611510705016014171 0ustar drazzibdrazzib guice-3.0/guice.iml0000644000175000017500000000546511460133000014141 0ustar drazzibdrazzib guice-3.0/lib/0000755000175000017500000000000011340510376013112 5ustar drazzibdrazzibguice-3.0/lib/build/0000755000175000017500000000000011542721726014220 5ustar drazzibdrazzibguice-3.0/lib/build/guice-3.0.xml0000644000175000017500000074006011542721720016335 0ustar drazzibdrazzib guice-3.0/lib/build/guice-1.0.xml0000644000175000017500000017416311452444050016336 0ustar drazzibdrazzib guice-3.0/lib/build/README0000644000175000017500000000005311214265026015066 0ustar drazzibdrazzibThese libraries are not needed at runtime. guice-3.0/lib/build/guice-2.0.xml0000644000175000017500000044201711452444050016333 0ustar drazzibdrazzib guice-3.0/lib/build/jdiff/0000755000175000017500000000000011463306740015277 5ustar drazzibdrazzibguice-3.0/lib/build/jdiff/background.gif0000644000175000017500000000105711463276104020110 0ustar drazzibdrazzibGIF89ahh€õõõ!ù,hhÿ„©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡Ä¢ñˆL*—̦ó J§ÔªõŠÍj·Ü®÷ ‹Çä²ùŒN«×ì¶û ËçôºýŽÏë÷ü¾ÿ(8HXhxˆ˜¨¸ÈØèø)9IYiy‰™©¹ÉÙéù *:JZjzŠšªºÊÚêú +;K[k{‹›«»ËÛëû ,N^n~Žž®¾ÎÞîþ/?O_oŸ¯¿Ïßïÿ0 À <ˆ0¡Â… :|1¢Ä‰+Z¼ˆ1£Æÿ;zü2¤È‘$Kš<‰2¥Ê•,[º| 3¦Ì™4kÚ¼‰3§Î<{úü 4¨Ð¡D‹=Š4©Ò¥L›:} 5ªÔ©T«Z½Š5«Ö­\»zý 6¬Ø±dËš=‹6­ÚµlÛº} 7®Ü¹tëÚ½‹7¯Þ½|ûúý 8°àÁ„ >Œ8±âÅŒ;~ 9²äÉ”+[¾Œ9³æÍœ;{þ :´èѤK›>:µêÕ¬[»~ ;¶ìÙ´kÛ¾;·îݼ{ûþ <¸ðáÄ‹?Ž<¹òåÌ›;=ºôéÔ«[¿Ž=»öíÜ»{ÿ>¼øñäË›?>½úõìÛ»?¾üùôëÛ¿?¿þýüûûÿ O;guice-3.0/lib/build/jdiff/new.gif0000644000175000017500000000016411463276104016560 0ustar drazzibdrazzibGIF89a ‘ÀÀÀÿÿ!ù, EŒo‚Š!ÜâyÏÑD«“6ûÿq@‘Àif¤Æ ç“–*Û¦æëº±8±"ñz°Ü̉ȊÁ"2¹IA-ÌÅªÈ ´MTR;guice-3.0/lib/build/jdiff/Null.java0000644000175000017500000000041111463306740017050 0ustar drazzibdrazzib/** * This class is used only as a "null" argument for Javadoc when comparing * two API files. Javadoc has to have a package, .java or .class file as an * argument, even though JDiff doesn't use it. */ public class Null { public Null() { } } guice-3.0/lib/build/jdiff/black.gif0000644000175000017500000000143711463276104017047 0ustar drazzibdrazzibGIF89a÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,;guice-3.0/uploadApiDiffs.sh0000644000175000017500000000105511472543430015576 0ustar drazzibdrazzibrm -rf build/docs CV=3.0 # remove old api-diffs svn rm latest-api-diffs/$CV svn ci -m "Removed old $CV api diffs." latest-api-diffs/$CV # create new api-diffs ant jdiff cp -r build/docs/latest-api-diffs latest-api-diffs/$CV cp lib/build/jdiff/*.gif latest-api-diffs/$CV mv latest-api-diffs/$CV/$CV.xml latest-api-diffs # capture current javadoc snapshot ant javadoc cp -r build/docs/javadoc latest-api-diffs/$CV/javadoc # commit changes svn add latest-api-diffs/$CV svn ci -m "Added updated $CV api diffs." latest-api-diffs/$CV latest-api-diffs/$CV.xml guice-3.0/COPYING0000644000175000017500000002613611214265036013407 0ustar drazzibdrazzib Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. guice-3.0/build.properties0000644000175000017500000000231711510705016015560 0ustar drazzibdrazziblib.dir=lib src.dir=core/src test.dir=core/test servlet.src.dir=extensions/servlet/src spring.src.dir=extensions/spring/src assistedinject.src.dir=extensions/assistedinject/src jmx.src.dir=extensions/jmx/src jndi.src.dir=extensions/jndi/src throwingproviders.src.dir=extensions/throwingproviders/src multibindings.src.dir=extensions/multibindings/src privatemodules.src.dir=extensions/privatemodules/src lifecycle.src.dir=extensions/lifecycle/src persist.src.dir=extensions/persist/src struts2.src.dir=extensions/struts2/src grapher.src.dir=extensions/grapher/src build.dir=build javadoc.packagenames=com.google.inject,com.google.inject.spi,\ com.google.inject.matcher,\ com.google.inject.servlet,\ com.google.inject.name,\ com.google.inject.tools.jmx,\ com.google.inject.binder,\ com.google.inject.jndi,\ com.google.inject.spring,\ com.google.inject.assistedinject,\ com.google.inject.throwingproviders,\ com.google.inject.multibindings,\ com.google.inject.privatemodules,\ com.google.inject.util,\ com.google.inject.persist,\ com.google.inject.persist.finder,\ com.google.inject.persist.jpa test.class=com.google.inject.AllTests module=com.google.inject imports=!net.sf.cglib.*,!org.objectweb.asm.* guice-3.0/common.xml0000644000175000017500000001476111531415070014364 0ustar drazzibdrazzib guice-3.0/uploadJavadocs.sh0000644000175000017500000000054411463305550015644 0ustar drazzibdrazzibrm -rf build/docs svn rm latest-javadoc javadoc svn ci -m "Removed old Javadocs." latest-javadoc javadoc ant javadoc cp -r build/docs/javadoc latest-javadoc cp -r latest-javadoc javadoc mv build/docs/guice-*.xml lib/build svn add latest-javadoc javadoc lib/build/guice-*.xml svn ci -m "Added updated Javadocs." latest-javadoc javadoc lib/build/guice-*.xml guice-3.0/copy.sh0000644000175000017500000000405511460133000013642 0ustar drazzibdrazzib#!/bin/sh # Copies classes into Guice's internal package. client=/usr/local/google/clients/collect/google3 srcdir=core/src/com/google/inject/internal testdir=core/test/com/google/inject/internal filter() { sed 's/com.google.common.base.internal/com.google.inject.internal/' | \ sed 's/com.google.common.base/com.google.inject.internal/' | \ sed 's/com.google.common.collect/com.google.inject.internal/' } copy() { inFile=$1; fileName=`basename $inFile` dest=$2 destpath=$dest/$fileName filter < $client/${inFile} > $destpath } commonpath=java/com/google/common copy $commonpath/collect/ComputationException.java $srcdir copy $commonpath/collect/AsynchronousComputationException.java $srcdir copy $commonpath/collect/CustomConcurrentHashMap.java $srcdir copy $commonpath/collect/ExpirationTimer.java $srcdir copy $commonpath/collect/MapMaker.java $srcdir copy $commonpath/collect/NullOutputException.java $srcdir copy $commonpath/base/Function.java $srcdir copy $commonpath/base/Nullable.java $srcdir copy $commonpath/base/FinalizableReference.java $srcdir copy $commonpath/base/FinalizableReferenceQueue.java $srcdir copy $commonpath/base/internal/Finalizer.java $srcdir copy $commonpath/base/FinalizableWeakReference.java $srcdir copy $commonpath/base/FinalizableSoftReference.java $srcdir copy $commonpath/base/FinalizablePhantomReference.java $srcdir commontestspath=javatests/com/google/common copy $commontestspath/base/FinalizableReferenceQueueTest.java $testdir copy $commontestspath/collect/MapMakerTestSuite.java $testdir copy $commontestspath/collect/Jsr166HashMap.java $testdir copy $commontestspath/collect/Jsr166HashMapTest.java $testdir copy $commonpath/collect/ForwardingConcurrentMap.java $testdir copy $commonpath/collect/ForwardingMap.java $testdir copy $commonpath/collect/ForwardingCollection.java $testdir copy $commonpath/collect/ForwardingObject.java $testdir copy $commonpath/collect/ForwardingSet.java $testdir copy $commonpath/collect/ForwardingMap.java $testdir copy $commonpath/base/Preconditions.java $testdir chmod +w -R $srcdir $testdir guice-3.0/guice.ipr0000644000175000017500000011712111460133000014143 0ustar drazzibdrazzib guice-3.0/javadoc/0000755000175000017500000000000011542721736013763 5ustar drazzibdrazzib