Sisyphus repositório
Última atualização: 1 outubro 2023 | SRPMs: 18631 | Visitas: 37766765
en ru br
ALT Linux repositórios
S:4.2.3-alt1_6jpp11
5.0: 1.0-alt1_0.RC2.1jpp5

Group :: Desenvolvimento/Java
RPM: google-guice

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs e FR  Repocop 

Patch: GUICE_618_extensible_filter_pipeline.patch
Download


Description: Let sub-classes of GuiceFilter customize the servlet filter pipeline
Author: Stuart McCulloch <mcculls@gmail.com>
Bug-Google: http://code.google.com/p/google-guice/issues/detail?id=618
Last-Update: 2015-01-20
diff --git a/extensions/servlet/src/com/google/inject/servlet/AbstractFilterPipeline.java b/extensions/servlet/src/com/google/inject/servlet/AbstractFilterPipeline.java
new file mode 100644
index 0000000..ab8f746
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/AbstractFilterPipeline.java
@@ -0,0 +1,150 @@
+/**
+ * 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.common.collect.Sets;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+
+import java.io.IOException;
+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;
+
+/**
+ * Skeleton implementation of a central routing/dispatch class which uses a sequence of
+ * {@link FilterDefinition}s to filter requests before delegating to the servlet pipeline.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public abstract class AbstractFilterPipeline implements FilterPipeline {
+
+  private final AbstractServletPipeline servletPipeline;
+  private final Provider<ServletContext> 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;
+
+  protected AbstractFilterPipeline(Injector injector, AbstractServletPipeline servletPipeline,
+      Provider<ServletContext> servletContext) {
+    this.injector = injector;
+    this.servletPipeline = servletPipeline;
+    this.servletContext = servletContext;
+  }
+
+  /**
+   * @return {@code true} if any filter mappings exist; otherwise {@code false}
+   */
+  protected abstract boolean hasFiltersMapped();
+
+  /**
+   * @return snapshot of the filter mappings currently defined for this pipeline
+   */
+  protected abstract FilterDefinition[] filterDefinitions();
+
+  public synchronized void initPipeline(ServletContext servletContext)
+      throws ServletException {
+
+    //double-checked lock, prevents duplicate initialization
+    if (initialized)
+      return;
+
+    // Used to prevent duplicate initialization.
+    Set<Filter> initializedSoFar = Sets.newIdentityHashSet();
+
+    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 AbstractServletPipeline servletPipeline) {
+
+    // 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;
+    }
+
+    HttpServletRequest request = (HttpServletRequest) 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<Filter> destroyedSoFar = Sets.newIdentityHashSet();
+    for (FilterDefinition filterDefinition : filterDefinitions()) {
+      filterDefinition.destroy(destroyedSoFar);
+    }
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/AbstractServletPipeline.java b/extensions/servlet/src/com/google/inject/servlet/AbstractServletPipeline.java
new file mode 100644
index 0000000..811820a
--- /dev/null
+++ b/extensions/servlet/src/com/google/inject/servlet/AbstractServletPipeline.java
@@ -0,0 +1,187 @@
+/**
+ * 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.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.inject.Injector;
+
+import java.io.IOException;
+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;
+
+/**
+ * Skeleton implementation of a wrapping dispatcher for servlets based on a sequence of
+ * {@link ServletDefinition}s, much like {@link AbstractFilterPipeline} is for filters.
+ *
+ * @author dhanji@gmail.com (Dhanji R. Prasanna)
+ */
+public abstract class AbstractServletPipeline {
+
+  /**
+   * @return {@code true} if any servlet mappings exist; otherwise {@code false}
+   */
+  protected abstract boolean hasServletsMapped();
+
+  /**
+   * @return snapshot of the servlet mappings currently defined for this pipeline
+   */
+  protected abstract ServletDefinition[] servletDefinitions();
+
+  void init(ServletContext servletContext, Injector injector) throws ServletException {
+    Set<HttpServlet> initializedSoFar = Sets.newIdentityHashSet();
+
+    for (ServletDefinition servletDefinition : servletDefinitions()) {
+      servletDefinition.init(servletContext, injector, initializedSoFar);
+    }
+  }
+
+  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;
+  }
+
+  void destroy() {
+    Set<HttpServlet> destroyedSoFar = Sets.newIdentityHashSet();
+    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 = wrapRequest((HttpServletRequest)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;
+            }
+
+            // now dispatch to the servlet
+            doServiceImpl(servletDefinition, requestToProcess, servletResponse);
+          }
+
+          public void include(ServletRequest servletRequest, ServletResponse servletResponse)
+              throws ServletException, IOException {
+            // route to the target servlet
+            doServiceImpl(servletDefinition, servletRequest, servletResponse);
+          }
+
+          private void doServiceImpl(ServletDefinition servletDefinition, ServletRequest servletRequest,
+              ServletResponse servletResponse) throws ServletException, IOException {
+            servletRequest.setAttribute(REQUEST_DISPATCHER_REQUEST, Boolean.TRUE);
+
+            try {
+              servletDefinition.doService(servletRequest, servletResponse);
+            } finally {
+              servletRequest.removeAttribute(REQUEST_DISPATCHER_REQUEST);
+            }
+          }
+        };
+      }
+    }
+
+    //otherwise, can't process
+    return null;
+  }
+
+  // visible for testing
+  static HttpServletRequest wrapRequest(HttpServletRequest request, String newUri) {
+    return new RequestDispatcherRequestWrapper(request, newUri);
+  }
+
+  /**
+   * 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.
+   */
+  static final String REQUEST_DISPATCHER_REQUEST = "javax.servlet.forward.servlet_path";
+
+  private static class RequestDispatcherRequestWrapper extends HttpServletRequestWrapper {
+    private final String newRequestUri;
+
+    RequestDispatcherRequestWrapper(HttpServletRequest servletRequest, String newRequestUri) {
+      super(servletRequest);
+      this.newRequestUri = newRequestUri;
+    }
+
+    @Override
+    public String getRequestURI() {
+      return newRequestUri;
+    }
+
+    @Override
+    public StringBuffer getRequestURL() {
+      StringBuffer url = new StringBuffer();
+      String scheme = getScheme();
+      int port = getServerPort();
+
+      url.append(scheme);
+      url.append("://");
+      url.append(getServerName());
+      // port might be -1 in some cases (see java.net.URL.getPort)
+      if (port > 0 &&
+          (("http".equals(scheme) && (port != 80)) ||
+           ("https".equals(scheme) && (port != 443)))) {
+        url.append(':');
+        url.append(port);
+      }
+      url.append(getRequestURI());
+
+      return (url);
+    }
+  }
+}
diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java b/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java
index b4112cf..bfe5a83 100644
--- a/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java
+++ b/extensions/servlet/src/com/google/inject/servlet/FilterChainInvocation.java
@@ -50,7 +50,7 @@ class FilterChainInvocation implements FilterChain {
   
   private final FilterDefinition[] filterDefinitions;
   private final FilterChain proceedingChain;
-  private final ManagedServletPipeline servletPipeline;
+  private final AbstractServletPipeline servletPipeline;
 
   //state variable tracks current link in filterchain
   private int index = -1;
@@ -58,7 +58,7 @@ class FilterChainInvocation implements FilterChain {
   private boolean cleanedStacks = false;
 
   public FilterChainInvocation(FilterDefinition[] filterDefinitions,
-      ManagedServletPipeline servletPipeline, FilterChain proceedingChain) {
+      AbstractServletPipeline servletPipeline, FilterChain proceedingChain) {
 
     this.filterDefinitions = filterDefinitions;
     this.servletPipeline = servletPipeline;
diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java
index ff1e5b6..76ece31 100644
--- a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java
+++ b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java
@@ -37,11 +37,11 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 
 /**
- * An internal representation of a filter definition against a particular URI pattern.
+ * Defines a filter mapped to a URI pattern and performs the request filtering for that filter.
  *
  * @author dhanji@gmail.com (Dhanji R. Prasanna)
  */
-class FilterDefinition implements ProviderWithExtensionVisitor<FilterDefinition> {
+public class FilterDefinition implements ProviderWithExtensionVisitor<FilterDefinition> {
   private final String pattern;
   private final Key<? extends Filter> filterKey;
   private final UriPatternMatcher patternMatcher;
@@ -90,7 +90,7 @@ class FilterDefinition implements ProviderWithExtensionVisitor<FilterDefinition>
     return uri != null && patternMatcher.matches(uri);
   }
 
-  public void init(final ServletContext servletContext, Injector injector,
+  void init(final ServletContext servletContext, Injector injector,
       Set<Filter> initializedSoFar) throws ServletException {
 
     // This absolutely must be a singleton, and so is only initialized once.
@@ -130,7 +130,7 @@ class FilterDefinition implements ProviderWithExtensionVisitor<FilterDefinition>
     initializedSoFar.add(filter);
   }
 
-  public void destroy(Set<Filter> destroyedSoFar) {
+  void destroy(Set<Filter> destroyedSoFar) {
     // filters are always singletons
     Filter reference = filter.get();
 
@@ -150,7 +150,7 @@ class FilterDefinition implements ProviderWithExtensionVisitor<FilterDefinition>
     }
   }
 
-  public Filter getFilterIfMatching(HttpServletRequest request) {
+  Filter getFilterIfMatching(HttpServletRequest request) {
 
     final String path = ServletUtils.getContextRelativePath(request);
     if (shouldFilter(path)) {
diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java b/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java
index 985064b..c745d20 100644
--- a/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java
+++ b/extensions/servlet/src/com/google/inject/servlet/FilterPipeline.java
@@ -26,7 +26,7 @@ import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
 /**
- * An internal dispatcher for guice-servlet registered servlets and filters.
+ * A dispatcher abstraction 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.
  *
@@ -39,10 +39,27 @@ import javax.servlet.ServletResponse;
  * @author dhanji@gmail.com (Dhanji R. Prasanna)
  */
 @ImplementedBy(DefaultFilterPipeline.class)
-interface FilterPipeline {
+public interface FilterPipeline {
+
+  /**
+   * Initializes the pipeline, putting it into service.
+   * 
+   * @param context of the web application
+   */
   void initPipeline(ServletContext context) throws ServletException;
+
+  /**
+   * Destroys the pipeline, taking it out of service.
+   */
   void destroyPipeline();
 
+  /**
+   * Dispatches a request against the pipeline.
+   * 
+   * @param request to dispatch
+   * @param response to populate
+   * @param defaultFilterChain for last resort filtering
+   */
   void dispatch(ServletRequest request, ServletResponse response,
       FilterChain defaultFilterChain) throws IOException, ServletException;
 }
diff --git a/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java b/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
index ba7a5af..0737b38 100644
--- a/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
+++ b/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
@@ -89,7 +89,7 @@ public class GuiceFilter implements Filter {
     this(null);
   }
 
-  @Inject GuiceFilter(FilterPipeline filterPipeline) {
+  @Inject protected GuiceFilter(FilterPipeline filterPipeline) {
     injectedPipeline = filterPipeline;
   }
 
diff --git a/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java b/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java
index 538e10a..76bc269 100644
--- a/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java
+++ b/extensions/servlet/src/com/google/inject/servlet/ManagedFilterPipeline.java
@@ -16,7 +16,6 @@
 package com.google.inject.servlet;
 
 import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
 import com.google.inject.Binding;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -24,50 +23,41 @@ import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import com.google.inject.TypeLiteral;
 
-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.
+ * Managed implementation of a central routing/dispatch class which handles lifecycle of managed
+ * filters, and delegates to a managed servlet pipeline.
  *
  * @author dhanji@gmail.com (Dhanji R. Prasanna)
  */
 @Singleton
-class ManagedFilterPipeline implements FilterPipeline{
+class ManagedFilterPipeline extends AbstractFilterPipeline {
   private final FilterDefinition[] filterDefinitions;
-  private final ManagedServletPipeline servletPipeline;
-  private final Provider<ServletContext> 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<FilterDefinition> FILTER_DEFS =
       TypeLiteral.get(FilterDefinition.class);
 
   @Inject
   public ManagedFilterPipeline(Injector injector, ManagedServletPipeline servletPipeline,
       Provider<ServletContext> servletContext) {
-    this.injector = injector;
-    this.servletPipeline = servletPipeline;
-    this.servletContext = servletContext;
+    super(injector, servletPipeline, servletContext);
 
     this.filterDefinitions = collectFilterDefinitions(injector);
   }
 
+  @Override
+  protected boolean hasFiltersMapped() {
+    return filterDefinitions.length > 0;
+  }
+
+  @Override
+  protected FilterDefinition[] filterDefinitions() {
+    return filterDefinitions;
+  }
+
   /**
    * Introspects the injector and collects all instances of bound {@code List<FilterDefinition>}
    * into a master list.
@@ -84,86 +74,4 @@ class ManagedFilterPipeline implements FilterPipeline{
     // Copy to a fixed-size array for speed of iteration.
     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<Filter> initializedSoFar = Sets.newIdentityHashSet();
-
-    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) {
-
-    // 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;
-    }
-
-    HttpServletRequest request = (HttpServletRequest) 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<Filter> destroyedSoFar = Sets.newIdentityHashSet();
-    for (FilterDefinition filterDefinition : filterDefinitions) {
-      filterDefinition.destroy(destroyedSoFar);
-    }
-  }
 }
diff --git a/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java b/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java
index 455551a..ab58a8e 100644
--- a/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java
+++ b/extensions/servlet/src/com/google/inject/servlet/ManagedServletPipeline.java
@@ -15,27 +15,14 @@
  */
 package com.google.inject.servlet;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
 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 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
@@ -44,7 +31,7 @@ import javax.servlet.http.HttpServletRequestWrapper;
  * @author dhanji@gmail.com (Dhanji R. Prasanna)
  */
 @Singleton
-class ManagedServletPipeline {
+class ManagedServletPipeline extends AbstractServletPipeline {
   private final ServletDefinition[] servletDefinitions;
   private static final TypeLiteral<ServletDefinition> SERVLET_DEFS =
       TypeLiteral.get(ServletDefinition.class);
@@ -54,10 +41,16 @@ class ManagedServletPipeline {
     this.servletDefinitions = collectServletDefinitions(injector);
   }
 
-  boolean hasServletsMapped() {
+  @Override
+  protected boolean hasServletsMapped() {
     return servletDefinitions.length > 0;
   }
 
+  @Override
+  protected ServletDefinition[] servletDefinitions() {
+    return servletDefinitions;
+  }
+
   /**
    * Introspects the injector and collects all instances of bound {@code List<ServletDefinition>}
    * into a master list.
@@ -74,140 +67,4 @@ class ManagedServletPipeline {
     // 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<HttpServlet> initializedSoFar = Sets.newIdentityHashSet();
-
-    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<HttpServlet> destroyedSoFar = Sets.newIdentityHashSet();
-    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 = wrapRequest((HttpServletRequest)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;
-            }
-
-            // now dispatch to the servlet
-            doServiceImpl(servletDefinition, requestToProcess, servletResponse);
-          }
-
-          public void include(ServletRequest servletRequest, ServletResponse servletResponse)
-              throws ServletException, IOException {
-            // route to the target servlet
-            doServiceImpl(servletDefinition, servletRequest, servletResponse);
-          }
-
-          private void doServiceImpl(ServletDefinition servletDefinition, ServletRequest servletRequest,
-              ServletResponse servletResponse) throws ServletException, IOException {
-            servletRequest.setAttribute(REQUEST_DISPATCHER_REQUEST, Boolean.TRUE);
-
-            try {
-              servletDefinition.doService(servletRequest, servletResponse);
-            } finally {
-              servletRequest.removeAttribute(REQUEST_DISPATCHER_REQUEST);
-            }
-          }
-        };
-      }
-    }
-
-    //otherwise, can't process
-    return null;
-  }
-
-  // visible for testing
-  static HttpServletRequest wrapRequest(HttpServletRequest request, String newUri) {
-    return new RequestDispatcherRequestWrapper(request, newUri);
-  }
-
-  /**
-   * 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(HttpServletRequest servletRequest, String newRequestUri) {
-      super(servletRequest);
-      this.newRequestUri = newRequestUri;
-    }
-
-    @Override
-    public String getRequestURI() {
-      return newRequestUri;
-    }
-
-    @Override
-    public StringBuffer getRequestURL() {
-      StringBuffer url = new StringBuffer();
-      String scheme = getScheme();
-      int port = getServerPort();
-
-      url.append(scheme);
-      url.append("://");
-      url.append(getServerName());
-      // port might be -1 in some cases (see java.net.URL.getPort)
-      if (port > 0 &&
-          (("http".equals(scheme) && (port != 80)) ||
-           ("https".equals(scheme) && (port != 443)))) {
-        url.append(':');
-        url.append(port);
-      }
-      url.append(getRequestURI());
-
-      return (url);
-    }
-  }
 }
diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java b/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
index 11328ed..285ff31 100644
--- a/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
+++ b/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
@@ -46,12 +46,11 @@ import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;
 
 /**
- * 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 =)
+ * Defines a servlet mapped to a URI pattern and performs the request dispatch to that servlet.
  *
  * @author dhanji@gmail.com (Dhanji R. Prasanna)
  */
-class ServletDefinition implements ProviderWithExtensionVisitor<ServletDefinition> {
+public class ServletDefinition implements ProviderWithExtensionVisitor<ServletDefinition> {
   private final String pattern;
   private final Key<? extends HttpServlet> servletKey;
   private final UriPatternMatcher patternMatcher;
@@ -100,7 +99,7 @@ class ServletDefinition implements ProviderWithExtensionVisitor<ServletDefinitio
     return uri != null && patternMatcher.matches(uri);
   }
 
-  public void init(final ServletContext servletContext, Injector injector,
+  void init(final ServletContext servletContext, Injector injector,
       Set<HttpServlet> initializedSoFar) throws ServletException {
 
     // This absolutely must be a singleton, and so is only initialized once.
@@ -140,7 +139,7 @@ class ServletDefinition implements ProviderWithExtensionVisitor<ServletDefinitio
     initializedSoFar.add(httpServlet);
   }
 
-  public void destroy(Set<HttpServlet> destroyedSoFar) {
+  void destroy(Set<HttpServlet> destroyedSoFar) {
     HttpServlet reference = httpServlet.get();
 
     // Do nothing if this Servlet was invalid (usually due to not being scoped
@@ -169,7 +168,7 @@ class ServletDefinition implements ProviderWithExtensionVisitor<ServletDefinitio
    * @throws IOException If thrown by underlying servlet
    * @throws ServletException If thrown by underlying servlet
    */
-  public boolean service(ServletRequest servletRequest,
+  boolean service(ServletRequest servletRequest,
       ServletResponse servletResponse) throws IOException, ServletException {
 
     final HttpServletRequest request = (HttpServletRequest) servletRequest;
diff --git a/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java b/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java
index d8bac74..169dd89 100644
--- a/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java
+++ b/extensions/servlet/src/com/google/inject/servlet/UriPatternMatcher.java
@@ -22,7 +22,7 @@ package com.google.inject.servlet;
  *
  * @author dhanji@gmail.com (Dhanji R. Prasanna)
  */
-interface UriPatternMatcher {
+public interface UriPatternMatcher {
   /**
    * @param uri A "contextual" (i.e. relative) Request URI, *not* a complete one.
    * @return Returns true if the uri matches the pattern.
diff --git a/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java b/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java
index 80d6aea..c76199d 100644
--- a/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java
+++ b/extensions/servlet/src/com/google/inject/servlet/UriPatternType.java
@@ -26,7 +26,14 @@ import java.util.regex.Pattern;
 public enum UriPatternType {
   SERVLET, REGEX;
 
-  static UriPatternMatcher get(UriPatternType type, String pattern) {
+  /**
+   * Returns the appropriate {@link UriPatternMatcher} for {@code pattern}.
+   * 
+   * @param type of pattern matching
+   * @param pattern for matching URI
+   * @return {@link UriPatternMatcher} that matches the given pattern
+   */
+  public static UriPatternMatcher get(UriPatternType type, String pattern) {
     switch (type) {
       case SERVLET:
         return new ServletStyleUriPatternMatcher(pattern);
commit c2a5f1b0d3dc946bf4c9c240bce600ccf65230fa
Author: Stuart McCulloch <mcculls@gmail.com>
Date:   Tue Jan 20 18:51:01 2015 +0000
    Enhance logging in filter/servlet definitions
diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java
index 76ece31..6819665 100644
--- a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java
+++ b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java
@@ -15,6 +15,7 @@
  */
 package com.google.inject.servlet;
 
+import com.google.common.base.Strings;
 import com.google.common.collect.Iterators;
 import com.google.inject.Injector;
 import com.google.inject.Key;
@@ -29,6 +30,8 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterConfig;
@@ -42,6 +45,8 @@ import javax.servlet.http.HttpServletRequest;
  * @author dhanji@gmail.com (Dhanji R. Prasanna)
  */
 public class FilterDefinition implements ProviderWithExtensionVisitor<FilterDefinition> {
+  private static final Logger logger = Logger.getLogger(FilterDefinition.class.getName());
+
   private final String pattern;
   private final Key<? extends Filter> filterKey;
   private final UriPatternMatcher patternMatcher;
@@ -154,7 +159,11 @@ public class FilterDefinition implements ProviderWithExtensionVisitor<FilterDefi
 
     final String path = ServletUtils.getContextRelativePath(request);
     if (shouldFilter(path)) {
-      return filter.get();
+      Filter reference = filter.get();
+      if (logger.isLoggable(Level.FINEST)) {
+        logger.finest("Filtering " + path + " with " + reference);
+      }
+      return reference;
     } else {
       return null;
     }
@@ -164,4 +173,10 @@ public class FilterDefinition implements ProviderWithExtensionVisitor<FilterDefi
   Filter getFilter() {
     return filter.get();
   }
+
+  public String toPaddedString(int padding) {
+    Filter reference = filter.get();
+    return Strings.padEnd(pattern, padding, ' ') + ' '
+        + (reference != null ? reference : filterKey);
+  }
 }
diff --git a/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java b/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
index 0737b38..1a98bf4 100644
--- a/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
+++ b/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
@@ -99,9 +99,9 @@ public class GuiceFilter implements Filter {
 
     // 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.warning(MULTIPLE_INJECTORS_WARNING);
-    }
+    //if (GuiceFilter.pipeline instanceof ManagedFilterPipeline) {
+    //  LOGGER.warning(MULTIPLE_INJECTORS_WARNING);
+    //}
 
     // We overwrite the default pipeline
     GuiceFilter.pipeline = pipeline;
diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java b/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
index 285ff31..9e49ce5 100644
--- a/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
+++ b/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java
@@ -17,6 +17,7 @@ package com.google.inject.servlet;
 
 import static com.google.inject.servlet.ManagedServletPipeline.REQUEST_DISPATCHER_REQUEST;
 
+import com.google.common.base.Strings;
 import com.google.common.collect.Iterators;
 import com.google.inject.Injector;
 import com.google.inject.Key;
@@ -34,6 +35,8 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
@@ -51,6 +54,8 @@ import javax.servlet.http.HttpServletResponse;
  * @author dhanji@gmail.com (Dhanji R. Prasanna)
  */
 public class ServletDefinition implements ProviderWithExtensionVisitor<ServletDefinition> {
+  private static final Logger logger = Logger.getLogger(ServletDefinition.class.getName());
+
   private final String pattern;
   private final Key<? extends HttpServlet> servletKey;
   private final UriPatternMatcher patternMatcher;
@@ -283,7 +288,14 @@ public class ServletDefinition implements ProviderWithExtensionVisitor<ServletDe
         = (previous != null) ? previous.getOriginalRequest() : request;
     GuiceFilter.localContext.set(new GuiceFilter.Context(originalRequest, request, response));
     try {
-      httpServlet.get().service(request, response);
+      HttpServlet reference = httpServlet.get();
+      if (logger.isLoggable(Level.FINEST)) {
+        String path = ServletUtils.getContextRelativePath(request);
+        logger.finest("Serving " + path + " with " + reference);
+      }
+      if (reference != null) {
+        reference.service(request, response);
+      }
     } finally {
       GuiceFilter.localContext.set(previous);
     }
@@ -296,4 +308,10 @@ public class ServletDefinition implements ProviderWithExtensionVisitor<ServletDe
   String getPattern() {
     return pattern;
   }
+
+  public String toPaddedString(int padding) {
+    HttpServlet reference = httpServlet.get();
+    return Strings.padEnd(pattern, padding, ' ') + ' '
+        + (reference != null ? reference : servletKey);
+  }
 }
 
projeto & código: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
mantenedor atual: Michael Shigorin
mantenedor da tradução: Fernando Martini aka fmartini © 2009