Revision: 1230
Author: dhanji
Date: Mon Sep 13 15:18:14 2010
Log: Early support for thread-continuation of servlet request.
http://code.google.com/p/google-guice/source/detail?r=1230

Added:
/trunk/extensions/servlet/src/com/google/inject/servlet/ContinuingHttpServletRequest.java
Modified:
 /trunk/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java

=======================================
--- /dev/null
+++ /trunk/extensions/servlet/src/com/google/inject/servlet/ContinuingHttpServletRequest.java Mon Sep 13 15:18:14 2010
@@ -0,0 +1,72 @@
+/**
+ * Copyright (C) 2010 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.inject.OutOfScopeException;
+import com.google.inject.internal.util.Maps;
+import java.io.IOException;
+import java.util.Map;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpSession;
+
+/**
+ * A wrapper for requests that makes requests immutable, taking a snapshot
+ * of the original request.
+ *
+ * @author [email protected] (Dhanji R. Prasanna)
+ */
+class ContinuingHttpServletRequest extends HttpServletRequestWrapper {
+
+  // We clear out the attributes as they are mutable and not thread-safe.
+  private final Map<String, Object> attributes = Maps.newHashMap();
+
+  public ContinuingHttpServletRequest(HttpServletRequest request) {
+    super(request);
+  }
+
+  @Override public HttpSession getSession() {
+ throw new OutOfScopeException("Cannot access the session in a continued request");
+  }
+
+  @Override public HttpSession getSession(boolean create) {
+ throw new UnsupportedOperationException("Cannot access the session in a continued request");
+  }
+
+  @Override public ServletInputStream getInputStream() throws IOException {
+ throw new UnsupportedOperationException("Cannot access raw request on a continued request");
+  }
+
+  @Override public void setAttribute(String name, Object o) {
+    attributes.put(name, o);
+  }
+
+  @Override public void removeAttribute(String name) {
+    attributes.remove(name);
+  }
+
+  @Override public Object getAttribute(String name) {
+    return attributes.get(name);
+  }
+
+  @Override public Cookie[] getCookies() {
+    // TODO(dhanji): Cookies themselves are mutable. Is this a problem?
+    return super.getCookies().clone();
+  }
+}
=======================================
--- /trunk/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java Wed Aug 12 12:24:11 2009 +++ /trunk/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java Mon Sep 13 15:18:14 2010
@@ -17,9 +17,10 @@
 package com.google.inject.servlet;

 import com.google.inject.Key;
+import com.google.inject.OutOfScopeException;
 import com.google.inject.Provider;
 import com.google.inject.Scope;
-
+import java.util.concurrent.Callable;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;

@@ -103,4 +104,53 @@
       return "ServletScopes.SESSION";
     }
   };
-}
+
+  /**
+   * Wraps the given callable in a contextual callable that "continues" the
+   * HTTP request in another thread. This acts as a way of transporting
+   * request context data from the request processing thread to to worker
+   * threads.
+   * <p>
+   * There are some limitations:
+   * <ul>
+   *   <li>Derived objects (i.e. anything marked @RequestScoped will not be
+   *      transported.</li>
+ * <li>State changes to the HttpServletRequest after this method is called
+   *      will not be seen in the continued thread.</li>
+ * <li>Only the HttpServletRequest, ServletContext and request parameter + * map are available in the continued thread. The response and session
+   *      are not available.</li>
+   * </ul>
+   *
+ * @param callable code to be executed in another thread, which depends on
+   *     the request scope.
+ * @return a callable that will invoke the given callable, making the request
+   *     context available to it.
+ * @throws OutOfScopeException if this method is called from a non-request
+   *     thread, or if the request has completed.
+   */
+ public static <T> Callable<T> continueRequest(final Callable<T> callable) {
+    return new Callable<T>() {
+      private HttpServletRequest request =
+          new ContinuingHttpServletRequest(GuiceFilter.getRequest());
+
+      public T call() throws Exception {
+        GuiceFilter.Context context = GuiceFilter.localContext.get();
+        if (null == context) {
+          // Only set up the request continuation if we're running in a
+          // new vanilla thread.
+ GuiceFilter.localContext.set(new GuiceFilter.Context(request, null));
+        }
+        try {
+          return callable.call();
+        } finally {
+
+          // Clear the copied context if we set one up.
+          if (null == context) {
+            GuiceFilter.localContext.remove();
+          }
+        }
+      }
+    };
+  }
+}

--
You received this message because you are subscribed to the Google Groups 
"google-guice-dev" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice-dev?hl=en.

Reply via email to