1 /* 2 * Copyright (C) 2011 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.inject.servlet; 18 19 import static com.google.inject.name.Names.named; 20 import static java.lang.annotation.RetentionPolicy.RUNTIME; 21 22 import com.google.common.collect.ImmutableMap; 23 import com.google.inject.AbstractModule; 24 import com.google.inject.Binding; 25 import com.google.inject.Guice; 26 import com.google.inject.Injector; 27 import com.google.inject.Key; 28 import com.google.inject.Module; 29 import com.google.inject.PrivateModule; 30 import com.google.inject.Provides; 31 import com.google.inject.ScopeAnnotation; 32 import com.google.inject.Scopes; 33 import com.google.inject.Singleton; 34 import com.google.inject.name.Named; 35 import com.google.inject.spi.Element; 36 import com.google.inject.spi.Elements; 37 import com.google.inject.spi.PrivateElements; 38 import com.google.inject.util.Providers; 39 import java.lang.annotation.ElementType; 40 import java.lang.annotation.Retention; 41 import java.lang.annotation.Target; 42 import java.util.List; 43 import java.util.Map; 44 import junit.framework.TestCase; 45 46 /** 47 * Tests for {@link ServletScopes}. 48 * 49 * @author forster@google.com (Mike Forster) 50 */ 51 public class ServletScopesTest extends TestCase { testIsRequestScopedPositive()52 public void testIsRequestScopedPositive() { 53 final Key<String> a = Key.get(String.class, named("A")); 54 final Key<String> b = Key.get(String.class, named("B")); 55 final Key<String> c = Key.get(String.class, named("C")); 56 final Key<String> d = Key.get(String.class, named("D")); 57 final Key<Object> e = Key.get(Object.class, named("E")); 58 final Key<String> f = Key.get(String.class, named("F")); 59 final Key<String> g = Key.get(String.class, named("G")); 60 61 Module requestScopedBindings = 62 new AbstractModule() { 63 @Override 64 protected void configure() { 65 bind(a).to(b); 66 bind(b).to(c); 67 bind(c).toProvider(Providers.of("c")).in(ServletScopes.REQUEST); 68 bind(d).toProvider(Providers.of("d")).in(RequestScoped.class); 69 bind(e).to(AnnotatedRequestScopedClass.class); 70 install( 71 new PrivateModule() { 72 @Override 73 protected void configure() { 74 bind(f).toProvider(Providers.of("f")).in(RequestScoped.class); 75 expose(f); 76 } 77 }); 78 } 79 80 @Provides 81 @Named("G") 82 @RequestScoped 83 String provideG() { 84 return "g"; 85 } 86 }; 87 88 @SuppressWarnings("unchecked") // we know the module contains only bindings 89 List<Element> moduleBindings = Elements.getElements(requestScopedBindings); 90 ImmutableMap<Key<?>, Binding<?>> map = indexBindings(moduleBindings); 91 // linked bindings are not followed by modules 92 assertFalse(ServletScopes.isRequestScoped(map.get(a))); 93 assertFalse(ServletScopes.isRequestScoped(map.get(b))); 94 assertTrue(ServletScopes.isRequestScoped(map.get(c))); 95 assertTrue(ServletScopes.isRequestScoped(map.get(d))); 96 // annotated classes are not followed by modules 97 assertFalse(ServletScopes.isRequestScoped(map.get(e))); 98 assertTrue(ServletScopes.isRequestScoped(map.get(f))); 99 assertTrue(ServletScopes.isRequestScoped(map.get(g))); 100 101 Injector injector = Guice.createInjector(requestScopedBindings, new ServletModule()); 102 assertTrue(ServletScopes.isRequestScoped(injector.getBinding(a))); 103 assertTrue(ServletScopes.isRequestScoped(injector.getBinding(b))); 104 assertTrue(ServletScopes.isRequestScoped(injector.getBinding(c))); 105 assertTrue(ServletScopes.isRequestScoped(injector.getBinding(d))); 106 assertTrue(ServletScopes.isRequestScoped(injector.getBinding(e))); 107 assertTrue(ServletScopes.isRequestScoped(injector.getBinding(f))); 108 assertTrue(ServletScopes.isRequestScoped(injector.getBinding(g))); 109 } 110 testIsRequestScopedNegative()111 public void testIsRequestScopedNegative() { 112 final Key<String> a = Key.get(String.class, named("A")); 113 final Key<String> b = Key.get(String.class, named("B")); 114 final Key<String> c = Key.get(String.class, named("C")); 115 final Key<String> d = Key.get(String.class, named("D")); 116 final Key<String> e = Key.get(String.class, named("E")); 117 final Key<String> f = Key.get(String.class, named("F")); 118 final Key<String> g = Key.get(String.class, named("G")); 119 final Key<String> h = Key.get(String.class, named("H")); 120 final Key<String> i = Key.get(String.class, named("I")); 121 final Key<String> j = Key.get(String.class, named("J")); 122 123 Module requestScopedBindings = 124 new AbstractModule() { 125 @Override 126 protected void configure() { 127 bind(a).to(b); 128 bind(b).to(c); 129 bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE); 130 bind(d).toInstance("d"); 131 bind(e).toProvider(Providers.of("e")).asEagerSingleton(); 132 bind(f).toProvider(Providers.of("f")).in(Scopes.SINGLETON); 133 bind(g).toProvider(Providers.of("g")).in(Singleton.class); 134 bind(h).toProvider(Providers.of("h")).in(CustomScoped.class); 135 bindScope(CustomScoped.class, Scopes.NO_SCOPE); 136 install( 137 new PrivateModule() { 138 @Override 139 protected void configure() { 140 bind(i).toProvider(Providers.of("i")).in(CustomScoped.class); 141 expose(i); 142 } 143 }); 144 } 145 146 @Provides 147 @Named("J") 148 @CustomScoped 149 String provideJ() { 150 return "j"; 151 } 152 }; 153 154 @SuppressWarnings("unchecked") // we know the module contains only bindings 155 List<Element> moduleBindings = Elements.getElements(requestScopedBindings); 156 ImmutableMap<Key<?>, Binding<?>> map = indexBindings(moduleBindings); 157 assertFalse(ServletScopes.isRequestScoped(map.get(a))); 158 assertFalse(ServletScopes.isRequestScoped(map.get(b))); 159 assertFalse(ServletScopes.isRequestScoped(map.get(c))); 160 assertFalse(ServletScopes.isRequestScoped(map.get(d))); 161 assertFalse(ServletScopes.isRequestScoped(map.get(e))); 162 assertFalse(ServletScopes.isRequestScoped(map.get(f))); 163 assertFalse(ServletScopes.isRequestScoped(map.get(g))); 164 assertFalse(ServletScopes.isRequestScoped(map.get(h))); 165 assertFalse(ServletScopes.isRequestScoped(map.get(i))); 166 assertFalse(ServletScopes.isRequestScoped(map.get(j))); 167 168 Injector injector = Guice.createInjector(requestScopedBindings); 169 assertFalse(ServletScopes.isRequestScoped(injector.getBinding(a))); 170 assertFalse(ServletScopes.isRequestScoped(injector.getBinding(b))); 171 assertFalse(ServletScopes.isRequestScoped(injector.getBinding(c))); 172 assertFalse(ServletScopes.isRequestScoped(injector.getBinding(d))); 173 assertFalse(ServletScopes.isRequestScoped(injector.getBinding(e))); 174 assertFalse(ServletScopes.isRequestScoped(injector.getBinding(f))); 175 assertFalse(ServletScopes.isRequestScoped(injector.getBinding(g))); 176 assertFalse(ServletScopes.isRequestScoped(injector.getBinding(h))); 177 assertFalse(ServletScopes.isRequestScoped(injector.getBinding(i))); 178 assertFalse(ServletScopes.isRequestScoped(injector.getBinding(j))); 179 } 180 181 @RequestScoped 182 static class AnnotatedRequestScopedClass {} 183 184 @Target({ElementType.TYPE, ElementType.METHOD}) 185 @Retention(RUNTIME) 186 @ScopeAnnotation 187 private @interface CustomScoped {} 188 indexBindings(Iterable<Element> elements)189 private ImmutableMap<Key<?>, Binding<?>> indexBindings(Iterable<Element> elements) { 190 ImmutableMap.Builder<Key<?>, Binding<?>> builder = ImmutableMap.builder(); 191 for (Element element : elements) { 192 if (element instanceof Binding) { 193 Binding<?> binding = (Binding<?>) element; 194 builder.put(binding.getKey(), binding); 195 } else if (element instanceof PrivateElements) { 196 PrivateElements privateElements = (PrivateElements) element; 197 Map<Key<?>, Binding<?>> privateBindings = indexBindings(privateElements.getElements()); 198 for (Key<?> exposed : privateElements.getExposedKeys()) { 199 builder.put(exposed, privateBindings.get(exposed)); 200 } 201 } 202 } 203 return builder.build(); 204 } 205 } 206