Home | History | Annotate | Download | only in servlet
      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 (at) google.com (Mike Forster)
     50  */
     51 public class ServletScopesTest extends TestCase {
     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 
    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 
    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