Home | History | Annotate | Download | only in servlet
      1 /**
      2  * Copyright (C) 2009 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 package com.google.inject.servlet;
     17 
     18 import static com.google.inject.servlet.ServletScopes.REQUEST;
     19 import static com.google.inject.servlet.ServletScopes.SESSION;
     20 
     21 import com.google.inject.AbstractModule;
     22 import com.google.inject.Inject;
     23 import com.google.inject.Key;
     24 import com.google.inject.Provider;
     25 import com.google.inject.Provides;
     26 import com.google.inject.Singleton;
     27 
     28 import java.util.Map;
     29 import java.util.logging.Logger;
     30 
     31 import javax.servlet.ServletContext;
     32 import javax.servlet.ServletRequest;
     33 import javax.servlet.ServletResponse;
     34 import javax.servlet.http.HttpServletRequest;
     35 import javax.servlet.http.HttpServletResponse;
     36 import javax.servlet.http.HttpSession;
     37 
     38 /**
     39  * This is a left-factoring of all ServletModules installed in the system.
     40  * In other words, this module contains the bindings common to all ServletModules,
     41  * and is bound exactly once per injector.
     42  *
     43  * @author dhanji (at) gmail.com (Dhanji R. Prasanna)
     44  */
     45 final class InternalServletModule extends AbstractModule {
     46 
     47   /**
     48    * Special Provider that tries to obtain an injected servlet context, specific
     49    * to the current injector, failing which, it falls back to the static singleton
     50    * instance that is available in the legacy Guice Servlet.
     51    */
     52   @Singleton
     53   static class BackwardsCompatibleServletContextProvider implements Provider<ServletContext> {
     54     private ServletContext injectedServletContext;
     55 
     56     @Inject BackwardsCompatibleServletContextProvider() {}
     57 
     58     // This setter is called by the GuiceServletContextListener
     59     void set(ServletContext injectedServletContext) {
     60       this.injectedServletContext = injectedServletContext;
     61     }
     62 
     63     public ServletContext get() {
     64       if (null != injectedServletContext) {
     65         return injectedServletContext;
     66       }
     67 
     68       Logger.getLogger(InternalServletModule.class.getName())
     69           .warning("You are attempting to use a deprecated API (specifically,"
     70           + " attempting to @Inject ServletContext inside an eagerly created"
     71           + " singleton. While we allow this for backwards compatibility, be"
     72           + " warned that this MAY have unexpected behavior if you have more"
     73           + " than one injector (with ServletModule) running in the same JVM."
     74           + " Please consult the Guice documentation at"
     75           + " https://github.com/google/guice/wiki/Servlets for more"
     76           + " information.");
     77       return GuiceFilter.getServletContext();
     78     }
     79   }
     80 
     81   @Override
     82   protected void configure() {
     83     bindScope(RequestScoped.class, REQUEST);
     84     bindScope(SessionScoped.class, SESSION);
     85     bind(ServletRequest.class).to(HttpServletRequest.class);
     86     bind(ServletResponse.class).to(HttpServletResponse.class);
     87 
     88     // inject the pipeline into GuiceFilter so it can route requests correctly
     89     // Unfortunate staticness... =(
     90     // NOTE(dhanji): This is maintained for legacy purposes.
     91     requestStaticInjection(GuiceFilter.class);
     92 
     93     bind(ManagedFilterPipeline.class);
     94     bind(ManagedServletPipeline.class);
     95     bind(FilterPipeline.class).to(ManagedFilterPipeline.class).asEagerSingleton();
     96 
     97     bind(ServletContext.class).toProvider(BackwardsCompatibleServletContextProvider.class);
     98     bind(BackwardsCompatibleServletContextProvider.class);
     99   }
    100 
    101   @Provides @Singleton @ScopingOnly GuiceFilter provideScopingOnlyGuiceFilter() {
    102     return new GuiceFilter(new DefaultFilterPipeline());
    103   }
    104 
    105   @Provides @RequestScoped HttpServletRequest provideHttpServletRequest() {
    106     return GuiceFilter.getRequest(Key.get(HttpServletRequest.class));
    107   }
    108 
    109   @Provides @RequestScoped HttpServletResponse provideHttpServletResponse() {
    110     return GuiceFilter.getResponse(Key.get(HttpServletResponse.class));
    111   }
    112 
    113   @Provides HttpSession provideHttpSession() {
    114     return GuiceFilter.getRequest(Key.get(HttpSession.class)).getSession();
    115   }
    116 
    117   @SuppressWarnings("unchecked") // defined by getParameterMap()
    118   @Provides @RequestScoped @RequestParameters Map<String, String[]> provideRequestParameters(
    119       ServletRequest req) {
    120     return req.getParameterMap();
    121   }
    122 
    123   @Override
    124   public boolean equals(Object o) {
    125     // Is only ever installed internally, so we don't need to check state.
    126     return o instanceof InternalServletModule;
    127   }
    128 
    129   @Override
    130   public int hashCode() {
    131     return InternalServletModule.class.hashCode();
    132   }
    133 }
    134