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 
     40 import junit.framework.TestCase;
     41 
     42 import java.lang.annotation.ElementType;
     43 import java.lang.annotation.Retention;
     44 import java.lang.annotation.Target;
     45 import java.util.List;
     46 import java.util.Map;
     47 
     48 /**
     49  * Tests for {@link ServletScopes}.
     50  *
     51  * @author forster (at) google.com (Mike Forster)
     52  */
     53 public class ServletScopesTest extends TestCase {
     54   public void testIsRequestScopedPositive() {
     55     final Key<String> a = Key.get(String.class, named("A"));
     56     final Key<String> b = Key.get(String.class, named("B"));
     57     final Key<String> c = Key.get(String.class, named("C"));
     58     final Key<String> d = Key.get(String.class, named("D"));
     59     final Key<Object> e = Key.get(Object.class, named("E"));
     60     final Key<String> f = Key.get(String.class, named("F"));
     61     final Key<String> g = Key.get(String.class, named("G"));
     62 
     63     Module requestScopedBindings = new AbstractModule() {
     64       @Override
     65       protected void configure() {
     66         bind(a).to(b);
     67         bind(b).to(c);
     68         bind(c).toProvider(Providers.of("c")).in(ServletScopes.REQUEST);
     69         bind(d).toProvider(Providers.of("d")).in(RequestScoped.class);
     70         bind(e).to(AnnotatedRequestScopedClass.class);
     71         install(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 = new AbstractModule() {
    124       @Override
    125       protected void configure() {
    126         bind(a).to(b);
    127         bind(b).to(c);
    128         bind(c).toProvider(Providers.of("c")).in(Scopes.NO_SCOPE);
    129         bind(d).toInstance("d");
    130         bind(e).toProvider(Providers.of("e")).asEagerSingleton();
    131         bind(f).toProvider(Providers.of("f")).in(Scopes.SINGLETON);
    132         bind(g).toProvider(Providers.of("g")).in(Singleton.class);
    133         bind(h).toProvider(Providers.of("h")).in(CustomScoped.class);
    134         bindScope(CustomScoped.class, Scopes.NO_SCOPE);
    135         install(new PrivateModule() {
    136           @Override
    137           protected void configure() {
    138             bind(i).toProvider(Providers.of("i")).in(CustomScoped.class);
    139             expose(i);
    140           }
    141         });
    142       }
    143 
    144       @Provides
    145       @Named("J")
    146       @CustomScoped
    147       String provideJ() {
    148         return "j";
    149       }
    150     };
    151 
    152     @SuppressWarnings("unchecked") // we know the module contains only bindings
    153     List<Element> moduleBindings = Elements.getElements(requestScopedBindings);
    154     ImmutableMap<Key<?>, Binding<?>> map = indexBindings(moduleBindings);
    155     assertFalse(ServletScopes.isRequestScoped(map.get(a)));
    156     assertFalse(ServletScopes.isRequestScoped(map.get(b)));
    157     assertFalse(ServletScopes.isRequestScoped(map.get(c)));
    158     assertFalse(ServletScopes.isRequestScoped(map.get(d)));
    159     assertFalse(ServletScopes.isRequestScoped(map.get(e)));
    160     assertFalse(ServletScopes.isRequestScoped(map.get(f)));
    161     assertFalse(ServletScopes.isRequestScoped(map.get(g)));
    162     assertFalse(ServletScopes.isRequestScoped(map.get(h)));
    163     assertFalse(ServletScopes.isRequestScoped(map.get(i)));
    164     assertFalse(ServletScopes.isRequestScoped(map.get(j)));
    165 
    166     Injector injector = Guice.createInjector(requestScopedBindings);
    167     assertFalse(ServletScopes.isRequestScoped(injector.getBinding(a)));
    168     assertFalse(ServletScopes.isRequestScoped(injector.getBinding(b)));
    169     assertFalse(ServletScopes.isRequestScoped(injector.getBinding(c)));
    170     assertFalse(ServletScopes.isRequestScoped(injector.getBinding(d)));
    171     assertFalse(ServletScopes.isRequestScoped(injector.getBinding(e)));
    172     assertFalse(ServletScopes.isRequestScoped(injector.getBinding(f)));
    173     assertFalse(ServletScopes.isRequestScoped(injector.getBinding(g)));
    174     assertFalse(ServletScopes.isRequestScoped(injector.getBinding(h)));
    175     assertFalse(ServletScopes.isRequestScoped(injector.getBinding(i)));
    176     assertFalse(ServletScopes.isRequestScoped(injector.getBinding(j)));
    177   }
    178 
    179   @RequestScoped
    180   static class AnnotatedRequestScopedClass {}
    181 
    182   @Target({ ElementType.TYPE, ElementType.METHOD })
    183   @Retention(RUNTIME)
    184   @ScopeAnnotation
    185   private @interface CustomScoped {}
    186 
    187   private ImmutableMap<Key<?>, Binding<?>> indexBindings(Iterable<Element> elements) {
    188     ImmutableMap.Builder<Key<?>, Binding<?>> builder = ImmutableMap.builder();
    189     for (Element element : elements) {
    190       if (element instanceof Binding) {
    191         Binding<?> binding = (Binding<?>) element;
    192         builder.put(binding.getKey(), binding);
    193       } else if (element instanceof PrivateElements) {
    194         PrivateElements privateElements = (PrivateElements) element;
    195         Map<Key<?>, Binding<?>> privateBindings = indexBindings(privateElements.getElements());
    196         for (Key<?> exposed : privateElements.getExposedKeys()) {
    197           builder.put(exposed, privateBindings.get(exposed));
    198         }
    199       }
    200     }
    201     return builder.build();
    202   }
    203 }
    204