Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / tools / development / DevAppEngineWebAppContext.java
blobf25e9cab8ce909b98edf1a35b2467d0da3165f72
1 // Copyright 2008 Google Inc. All Rights Reserved.
3 package com.google.appengine.tools.development;
5 import com.google.appengine.tools.info.SdkInfo;
6 import com.google.apphosting.utils.io.IoUtil;
7 import com.google.apphosting.utils.jetty.AppEngineWebAppContext;
9 import org.mortbay.jetty.security.ConstraintMapping;
11 import java.io.File;
12 import java.io.IOException;
13 import java.util.Enumeration;
14 import java.util.List;
15 import java.util.logging.Logger;
17 import javax.servlet.ServletException;
18 import javax.servlet.http.HttpServletRequest;
19 import javax.servlet.http.HttpServletResponse;
21 /**
22 * An AppEngineWebAppContext for the DevAppServer.
25 public class DevAppEngineWebAppContext extends AppEngineWebAppContext {
27 private static final Logger logger =
28 Logger.getLogger(DevAppEngineWebAppContext.class.getName());
30 private static final String JASPER_SERVLET_CLASSPATH = "org.apache.catalina.jsp_classpath";
32 private static final String X_GOOGLE_DEV_APPSERVER_SKIPADMINCHECK =
33 "X-Google-DevAppserver-SkipAdminCheck";
35 private static final String SKIP_ADMIN_CHECK_ATTR =
36 "com.google.apphosting.internal.SkipAdminCheck";
38 private final Object transportGuaranteeLock = new Object();
39 private boolean transportGuaranteesDisabled = false;
41 public DevAppEngineWebAppContext(File appDir, File externalResourceDir, String serverInfo,
42 ApiProxyLocal apiProxyLocal) {
43 super(appDir, serverInfo);
45 setAttribute(JASPER_SERVLET_CLASSPATH, buildClasspath());
47 _scontext.setAttribute("com.google.appengine.devappserver.ApiProxyLocal", apiProxyLocal);
49 if (externalResourceDir != null) {
50 try {
51 resolveWebApp();
52 setBaseResource(new ExtendedRootResource(getBaseResource(), externalResourceDir));
53 } catch (IOException e) {
54 throw new RuntimeException(e);
59 @Override
60 public void handle(String target, HttpServletRequest request, HttpServletResponse response,
61 int dispatch) throws IOException, ServletException {
63 if (hasSkipAdminCheck(request)) {
64 request.setAttribute(SKIP_ADMIN_CHECK_ATTR, Boolean.TRUE);
67 disableTransportGuarantee();
69 System.setProperty("devappserver-thread-" + Thread.currentThread().getName(), "true");
70 try {
71 super.handle(target, request, response, dispatch);
72 } finally {
73 System.clearProperty("devappserver-thread-" + Thread.currentThread().getName());
77 /**
78 * Returns true if the X-Google-Internal-SkipAdminCheck header is
79 * present. There is nothing preventing usercode from setting this header
80 * and circumventing dev appserver security, but the dev appserver was not
81 * designed to be secure.
83 private boolean hasSkipAdminCheck(HttpServletRequest request) {
84 for (Enumeration<?> headerNames = request.getHeaderNames(); headerNames.hasMoreElements(); ) {
85 String name = (String) headerNames.nextElement();
86 if (name.equalsIgnoreCase(X_GOOGLE_DEV_APPSERVER_SKIPADMINCHECK)) {
87 return true;
90 return false;
93 /**
94 * Builds a classpath up for the webapp for JSP compilation.
96 private String buildClasspath() {
97 StringBuffer classpath = new StringBuffer();
99 for (File f : SdkInfo.getSharedLibFiles()) {
100 classpath.append(f.getAbsolutePath());
101 classpath.append(File.pathSeparatorChar);
104 String webAppPath = getWar();
106 classpath.append(webAppPath + File.separator + "classes" + File.pathSeparatorChar);
108 List<File> files = IoUtil.getFilesAndDirectories(new File(webAppPath,"lib"));
109 for (File f : files) {
110 if (f.isFile() && f.getName().endsWith(".jar")) {
111 classpath.append(f.getAbsolutePath());
112 classpath.append(File.pathSeparatorChar);
116 return classpath.toString();
120 * The first time this method is called it will walk through the
121 * constraint mappings on the current SecurityHandler and disable
122 * any transport guarantees that have been set. This is required to
123 * disable SSL requirements in the DevAppServer because it does not
124 * support SSL.
126 private void disableTransportGuarantee() {
127 synchronized (transportGuaranteeLock) {
128 if (!transportGuaranteesDisabled) {
129 if (getSecurityHandler() != null) {
130 ConstraintMapping[] mappings = getSecurityHandler().getConstraintMappings();
131 if (mappings != null) {
132 for (ConstraintMapping mapping : mappings) {
133 if (mapping.getConstraint().getDataConstraint() > 0) {
134 logger.info("Ignoring <transport-guarantee> for " + mapping.getPathSpec() +
135 " as the SDK does not support HTTPS. It will still be used" +
136 " when you upload your application.");
137 mapping.getConstraint().setDataConstraint(0);
143 transportGuaranteesDisabled = true;