1 // Copyright 2008 Google Inc. All Rights Reserved.
3 package com
.google
.appengine
.tools
.development
;
5 import com
.google
.apphosting
.api
.ApiProxy
;
6 import com
.google
.apphosting
.utils
.config
.AppEngineWebXml
;
7 import com
.google
.apphosting
.utils
.config
.AppEngineWebXmlReader
;
8 import com
.google
.apphosting
.utils
.config
.WebModule
;
11 import java
.io
.IOException
;
12 import java
.io
.InputStream
;
13 import java
.util
.logging
.Logger
;
15 import javax
.servlet
.Filter
;
16 import javax
.servlet
.FilterChain
;
17 import javax
.servlet
.FilterConfig
;
18 import javax
.servlet
.ServletContext
;
19 import javax
.servlet
.ServletException
;
20 import javax
.servlet
.ServletRequest
;
21 import javax
.servlet
.ServletResponse
;
22 import javax
.servlet
.http
.HttpServletRequest
;
25 * This filter is not currently used. It was originally written for
26 * IBM so they could see how to use our API's from their own webserver.
27 * We kept it around because we'd ultimately like to use this ourselves but
28 * we don't currently have a way to ensure that this filter runs before any
29 * other filters get initialized.
31 * {@code LocalApiProxyServletFilter} is a servlet {@link Filter} that
32 * sets up {@link ApiProxy} for use with the stub API implementations.
34 * <p>There are two parts to this:<ul>
36 * <li>At initialization, this filter installs a {@link
37 * ApiProxy.Delegate} instance that locates any API stub
38 * implementations on the classpath and registers them for use by
39 * future requests. It also looks for an App Engine-specific
40 * deployment descriptor ({@code WEB-INF/appengine-web.xml}) and
41 * parses it to obtain some metadata about the application
42 * (e.g. application identifier).</li>
44 * <li>Around each request, a {@link ApiProxy.Environment} instance is
45 * installed into a {@link ThreadLocal} managed by {@link ApiProxy}.
46 * This environment instance contains the application metadata that
47 * was extracted earlier, and also provides access to the
48 * authentication data maintained by the stub implementation of the
49 * Users API.</li> </ul>
52 public class LocalApiProxyServletFilter
implements Filter
{
53 private static final Logger logger
= Logger
.getLogger(LocalApiProxyServletFilter
.class.getName());
54 private static final String AE_WEB_XML
= "/WEB-INF/appengine-web.xml";
56 private AppEngineWebXml appEngineWebXml
;
59 * Register a custom {@link ApiProxy.Delegate instance}.
62 public void init(FilterConfig config
) {
63 logger
.info("Filter initialization invoked -- registering ApiProxy delegate.");
64 ApiProxyLocalFactory factory
= new ApiProxyLocalFactory();
65 ApiProxy
.setDelegate(factory
.create(getLocalServerEnvironment(config
)));
67 logger
.info("Parsing custom deployment descriptor (" + AE_WEB_XML
+ ").");
68 ServletAppEngineWebXmlReader reader
=
69 new ServletAppEngineWebXmlReader(config
.getServletContext());
70 appEngineWebXml
= reader
.readAppEngineWebXml();
71 logger
.info("Application identifier is: " + appEngineWebXml
.getAppId());
74 private LocalServerEnvironment
getLocalServerEnvironment(final FilterConfig config
) {
75 return new LocalServerEnvironment() {
78 public File
getAppDir() {
83 public String
getAddress() {
84 throw new UnsupportedOperationException();
88 public int getPort() {
89 throw new UnsupportedOperationException();
93 public String
getHostName() {
94 throw new UnsupportedOperationException();
98 public void waitForServerToStart() { }
101 public boolean simulateProductionLatencies() {
106 public boolean enforceApiDeadlines() {
113 * Remove the custom {@link ApiProxy.Delegate} instance.
116 public void destroy() {
117 logger
.info("Filter destruction invoked -- removing delegate.");
118 ApiProxy
.setDelegate(null);
122 * Wrap the request with calls to the environment-management method
123 * on {@link ApiProxy}.
126 public void doFilter(ServletRequest request
, ServletResponse response
, FilterChain chain
)
127 throws IOException
, ServletException
{
128 HttpServletRequest httpRequest
= (HttpServletRequest
) request
;
130 logger
.fine("Filter received a request, setting environment ThreadLocal.");
131 ApiProxy
.setEnvironmentForCurrentThread(new LocalHttpRequestEnvironment(
132 appEngineWebXml
.getAppId(), WebModule
.getServerName(appEngineWebXml
),
133 appEngineWebXml
.getMajorVersionId(), LocalEnvironment
.MAIN_INSTANCE
,
134 httpRequest
, null, null));
136 chain
.doFilter(request
, response
);
138 logger
.fine("Request has completed. Removing environment ThreadLocal.");
139 ApiProxy
.clearEnvironmentForCurrentThread();
144 * {@code ServletAppEngineWebXmlReader} is a specialization of
145 * {@link AppEngineWebXmlReader} that reads the custom deployment
146 * descriptor ({@code WEB-INF/appengine-web.xml}) from a {@link
147 * ServletContext} rather than looking for an actual file on the
150 private static class ServletAppEngineWebXmlReader
extends AppEngineWebXmlReader
{
151 private final ServletContext context
;
153 public ServletAppEngineWebXmlReader(ServletContext context
) {
155 this.context
= context
;
159 protected InputStream
getInputStream() {
160 return context
.getResourceAsStream(AE_WEB_XML
);