diff --git a/README.md b/README.md index c8d7d5a..4bf3c84 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,11 @@ To use custom build docker image as the basis for a Java Web Application Archive First, build custom docker image of jetty9-compat, push to google cloud repo. mvn clean install + # For latest docker beta on Mac, use mvn install -DdockerHost=unix:///var/run/docker.sock docker tag -f jetty9-compat gcr.io//jetty9-compat: gcloud docker push gcr.io//jetty9-compat: -Then, use your custom docker image in the Dcokerfile, and run the App Engine flexible environment container via the Cloud SDK. +Then, use your custom docker image in the Dockerfile, and run the App Engine flexible environment container via the Cloud SDK. FROM gcr.io//jetty9-compat: ADD . /app diff --git a/appengine-java-logging/pom.xml b/appengine-java-logging/pom.xml index d94f0ee..80c4b17 100644 --- a/appengine-java-logging/pom.xml +++ b/appengine-java-logging/pom.xml @@ -21,7 +21,7 @@ com.google.appengine appengine-java-vm-runtime - 1.9.38-SNAPSHOT + 1.9.40-SNAPSHOT ../pom.xml Google App Engine Logging Support diff --git a/appengine-managed-runtime/pom.xml b/appengine-managed-runtime/pom.xml index 256f925..2959b33 100644 --- a/appengine-managed-runtime/pom.xml +++ b/appengine-managed-runtime/pom.xml @@ -21,7 +21,7 @@ com.google.appengine appengine-java-vm-runtime - 1.9.38-SNAPSHOT + 1.9.40-SNAPSHOT ../pom.xml Google App Engine Runtime Utilities @@ -36,7 +36,7 @@ com.google.appengine appengine-java-logging - 1.9.38-SNAPSHOT + 1.9.40-SNAPSHOT com.google.appengine diff --git a/appengine-managed-runtime/src/main/java/com/google/apphosting/utils/config/AppEngineWebXml.java b/appengine-managed-runtime/src/main/java/com/google/apphosting/utils/config/AppEngineWebXml.java index 59819ac..a8ce9e1 100644 --- a/appengine-managed-runtime/src/main/java/com/google/apphosting/utils/config/AppEngineWebXml.java +++ b/appengine-managed-runtime/src/main/java/com/google/apphosting/utils/config/AppEngineWebXml.java @@ -72,6 +72,14 @@ public static enum ScalingType { public static final String URL_HANDLER_URLFETCH = "urlfetch"; public static final String URL_HANDLER_NATIVE = "native"; + // Runtime ids. + private static final String JAVA_7_RUNTIME_ID = "java7"; + // Should accept java8* for multiple variations of Java8. + private static final String JAVA_8_RUNTIME_ID = "java8"; + // This was used for Java6, but now is used only for Managed VMs, + // not for standard editiom. + private static final String JAVA_RUNTIME_ID = "java"; + private String appId; private String majorVersionId; @@ -85,7 +93,7 @@ public static enum ScalingType { private final ManualScaling manualScaling; private final BasicScaling basicScaling; - private String sourceLanguage; + private String runtime; private boolean sslEnabled = true; private boolean useSessions = false; private boolean asyncSessionPersistence = false; @@ -235,12 +243,21 @@ public void setMajorVersionId(String majorVersionId) { this.majorVersionId = majorVersionId; } - public String getSourceLanguage() { - return this.sourceLanguage; + public String getRuntime() { + if (runtime != null) { + return runtime; + } + // The new env:flex means java, not java7: + if (isFlexible()) { + runtime = JAVA_RUNTIME_ID; + } else { + runtime = JAVA_7_RUNTIME_ID; + } + return runtime; } - public void setSourceLanguage(String sourceLanguage) { - this.sourceLanguage = sourceLanguage; + public void setRuntime(String runtime) { + this.runtime = runtime; } public String getModule() { @@ -573,8 +590,8 @@ public String toString() { + ", majorVersionId='" + majorVersionId + '\'' - + ", sourceLanguage='" - + sourceLanguage + + ", runtime='" + + runtime + '\'' + ", service='" + service @@ -749,9 +766,9 @@ public boolean equals(Object o) { : that.majorVersionId != null) { return false; } - if (sourceLanguage != null - ? !sourceLanguage.equals(that.sourceLanguage) - : that.sourceLanguage != null) { + if (runtime != null + ? !runtime.equals(that.runtime) + : that.runtime != null) { return false; } if (publicRoot != null ? !publicRoot.equals(that.publicRoot) : that.publicRoot != null) { @@ -853,7 +870,7 @@ public int hashCode() { result = 31 * result + (userPermissions != null ? userPermissions.hashCode() : 0); result = 31 * result + (appId != null ? appId.hashCode() : 0); result = 31 * result + (majorVersionId != null ? majorVersionId.hashCode() : 0); - result = 31 * result + (sourceLanguage != null ? sourceLanguage.hashCode() : 0); + result = 31 * result + (runtime != null ? runtime.hashCode() : 0); result = 31 * result + (service != null ? service.hashCode() : 0); result = 31 * result + (instanceClass != null ? instanceClass.hashCode() : 0); result = 31 * result + automaticScaling.hashCode(); diff --git a/appengine-managed-runtime/src/main/java/com/google/apphosting/utils/config/AppEngineWebXmlProcessor.java b/appengine-managed-runtime/src/main/java/com/google/apphosting/utils/config/AppEngineWebXmlProcessor.java index 290847d..3a4de0b 100644 --- a/appengine-managed-runtime/src/main/java/com/google/apphosting/utils/config/AppEngineWebXmlProcessor.java +++ b/appengine-managed-runtime/src/main/java/com/google/apphosting/utils/config/AppEngineWebXmlProcessor.java @@ -136,11 +136,14 @@ private void processSecondLevelNode(Element elt, AppEngineWebXml appEngineWebXml case "application": processApplicationNode(elt, appEngineWebXml); break; + case "runtime": + processRuntimeNode(elt, appEngineWebXml); + break; case "version": processVersionNode(elt, appEngineWebXml); break; case "source-language": - processSourceLanguageNode(elt, appEngineWebXml); + // Obsolete, ignore. break; case "module": moduleNodeFound = true; @@ -242,8 +245,8 @@ private void processVersionNode(Element node, AppEngineWebXml appEngineWebXml) { appEngineWebXml.setMajorVersionId(XmlUtils.getText(node)); } - private void processSourceLanguageNode(Element node, AppEngineWebXml appEngineWebXml) { - appEngineWebXml.setSourceLanguage(XmlUtils.getText(node)); + private void processRuntimeNode(Element node, AppEngineWebXml appEngineWebXml) { + appEngineWebXml.setRuntime(XmlUtils.getText(node)); } private void processModuleNode(Element node, AppEngineWebXml appEngineWebXml) { diff --git a/jetty9-base/pom.xml b/jetty9-base/pom.xml index f4ea4fa..b76027e 100644 --- a/jetty9-base/pom.xml +++ b/jetty9-base/pom.xml @@ -21,7 +21,7 @@ com.google.appengine appengine-java-vm-runtime - 1.9.38-SNAPSHOT + 1.9.40-SNAPSHOT ../pom.xml Google App Engine Image Jetty (jetty9-base) @@ -125,7 +125,7 @@ -jar ../jetty-distribution-${jetty.version}/start.jar - --add-to-startd=gae,http,deploy,jsp,jstl + --add-to-startd=gae,http,jsp,jstl diff --git a/jetty9-base/src/main/jetty-base/etc/gae-web.xml b/jetty9-base/src/main/jetty-base/etc/gae-web.xml new file mode 100644 index 0000000..47215c6 --- /dev/null +++ b/jetty9-base/src/main/jetty-base/etc/gae-web.xml @@ -0,0 +1,16 @@ + + + + + + + + + + /app.yaml + + + + + + diff --git a/jetty9-base/src/main/jetty-base/etc/gae.xml b/jetty9-base/src/main/jetty-base/etc/gae.xml index e7f112f..ccca81b 100644 --- a/jetty9-base/src/main/jetty-base/etc/gae.xml +++ b/jetty9-base/src/main/jetty-base/etc/gae.xml @@ -68,4 +68,18 @@ + + + + + + /etc/gae-web.xml + + + + + + + + diff --git a/jetty9-base/src/main/jetty-base/modules/gae.mod b/jetty9-base/src/main/jetty-base/modules/gae.mod index 7d7dde2..b74164b 100644 --- a/jetty9-base/src/main/jetty-base/modules/gae.mod +++ b/jetty9-base/src/main/jetty-base/modules/gae.mod @@ -5,6 +5,7 @@ [depend] resources server +deploy [optional] @@ -25,3 +26,5 @@ jetty.httpConfig.sendDateHeader=false #gae.httpPort=80 #gae.httpsPort=443 + +#jetty.server.stopTimeout=30000 diff --git a/jetty9-compat-base/pom.xml b/jetty9-compat-base/pom.xml index 4819905..19706a0 100644 --- a/jetty9-compat-base/pom.xml +++ b/jetty9-compat-base/pom.xml @@ -21,7 +21,7 @@ com.google.appengine appengine-java-vm-runtime - 1.9.38-SNAPSHOT + 1.9.40-SNAPSHOT ../pom.xml Google App Engine Container with GAE Compatibility (jetty9-compat-base) diff --git a/jetty9-compat-base/src/main/java/com/google/apphosting/vmruntime/jetty9/AppengineApiConfiguration.java b/jetty9-compat-base/src/main/java/com/google/apphosting/vmruntime/jetty9/AppengineApiConfiguration.java index b2d5217..13b7b86 100644 --- a/jetty9-compat-base/src/main/java/com/google/apphosting/vmruntime/jetty9/AppengineApiConfiguration.java +++ b/jetty9-compat-base/src/main/java/com/google/apphosting/vmruntime/jetty9/AppengineApiConfiguration.java @@ -16,133 +16,46 @@ package com.google.apphosting.vmruntime.jetty9; -import org.eclipse.jetty.util.URIUtil; -import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.AbstractConfiguration; -import org.eclipse.jetty.webapp.WebAppClassLoader; import org.eclipse.jetty.webapp.WebAppContext; -import java.util.logging.Level; - public class AppengineApiConfiguration extends AbstractConfiguration { // A class to check if the GAE API is available. public static final String GAE_CHECK_CLASS = "com.google.appengine.api.ThreadManager"; - // Hide the all container classes from the webapplication - // TODO update to use '.' when supported by Jetty - private static final String[] SERVER_CLASSES = { - "com.", - "javax.", - "org.", - "mozilla." + // It's undesirable to have the user app override classes provided by us. + // So we mark them as Jetty system classes, which cannot be overridden. + private static final String[] SYSTEM_CLASSES = { + "com.google.appengine.api.", + "com.google.appengine.tools.", + "com.google.apphosting.", + "com.google.cloud.sql.jdbc.", + "com.google.protos.cloud.sql.", + "com.google.storage.onestore.", }; - - // Classes & Packages to be shared from the containers classloader - // to the webapp. Classes included here will be marked both as - // exclusions from serverclasses (not hidden from webapp) and inclusion - // to the systemclasses (cannot be overriden by the webapp) - private static final String[] SHARED_CLASSES = { - // Expose the GAE API classes - "com.google.appengine.api.LifecycleManager", - "com.google.apphosting.api.ApiProxy", - "com.google.apphosting.api.ApiStats", - "com.google.apphosting.api.CloudTrace", - "com.google.apphosting.api.CloudTraceContext", - "com.google.apphosting.api.DeadlineExceededException", - "com.google.apphosting.runtime.SessionData", - "com.google.apphosting.runtime.UncatchableError", - - // Expose the standard APIs that are provided by the container - "javax.servlet.", - "javax.el.", - "javax.mail.", // TODO Review - - // Expose the standard APIs that are provided by the JVM - "com.oracle.", - "com.sun.", - "javax.accessibility.", - "javax.activation.", - "javax.activity.", - "javax.annotation.", - "javax.imageio.", - "javax.jws.", - "javax.lang.model.", - "javax.management.", - "javax.naming.", - "javax.net.", - "javax.print.", - "javax.rmi.", - "javax.script.", - "javax.security.", - "javax.smartcardio.", - "javax.sound.", - "javax.sql.", - "javax.swing.", - "javax.tools.", - "javax.transaction.", - "javax.xml.", - "jdk.", - "org.ietf.jgss.", - "org.jcp.xml.dsig.internal.", - "org.omg.", - "org.w3c.dom.", - "org.xml.", - "sun.", - - // Expose classes needed for JSP and JSTL - "org.apache.jasper.runtime.", - "org.apache.jasper.JasperException", - "org.apache.el.ExpressionFactoryImpl", - "org.apache.tomcat.InstanceManager", - "org.apache.taglibs.", + + // Hide the container classes from the webapplication + private static final String[] SERVER_CLASSES = { + "org.apache.commons.codec.", + "org.apache.commons.logging.", + "org.apache.http.", + "com.google.gson." }; @Override public void preConfigure(WebAppContext context) { + for (String systemClass : SYSTEM_CLASSES) { + context.addSystemClass(systemClass); + } for (String systemClass : SERVER_CLASSES) { context.addServerClass(systemClass); } - for (String gaeClass : SHARED_CLASSES) { - // Don't hide shared classes - context.prependServerClass("-" + gaeClass); - // Don't allow shared classes to be replaced by webapp - context.addSystemClass(gaeClass); - } } public void configure(WebAppContext context) throws Exception { ClassLoader loader = context.getClassLoader(); - try { - // Test if the appengine api is available - loader.loadClass(GAE_CHECK_CLASS); - } catch (Exception ex) { - if (VmRuntimeWebAppContext.logger.isLoggable(Level.FINE)) { - VmRuntimeWebAppContext.logger.log(Level.WARNING, - "No appengine API jar included in WEB-INF/lib! Please update your SDK!", ex); - } else { - VmRuntimeWebAppContext.logger.log(Level.WARNING, - "No appengine API jar included in WEB-INF/lib! Please update your SDK!"); - } - - // The appengine API is not available so we will add it and it's dependencies - Resource providedApi = - Resource.newResource( - URIUtil.addPaths(System.getProperty("jetty.base"), "/lib/gae/provided-api/")); - - if (providedApi != null) { - String[] list = providedApi.list(); - if (list != null) { - WebAppClassLoader wloader = (WebAppClassLoader) loader; - for (String jar : list) { - wloader.addClassPath(providedApi.addPath(jar)); - VmRuntimeWebAppContext.logger.log(Level.INFO, "Added " + jar + " to webapp classpath"); - } - } - } - - // Ensure the API can now be loaded - loader.loadClass(GAE_CHECK_CLASS); - } + // Ensure the API can be loaded + loader.loadClass(GAE_CHECK_CLASS); } } diff --git a/jetty9-compat-base/src/main/java/com/google/apphosting/vmruntime/jetty9/VmRuntimeWebAppContext.java b/jetty9-compat-base/src/main/java/com/google/apphosting/vmruntime/jetty9/VmRuntimeWebAppContext.java index 9f762a4..8ca3c5c 100644 --- a/jetty9-compat-base/src/main/java/com/google/apphosting/vmruntime/jetty9/VmRuntimeWebAppContext.java +++ b/jetty9-compat-base/src/main/java/com/google/apphosting/vmruntime/jetty9/VmRuntimeWebAppContext.java @@ -49,6 +49,7 @@ import org.eclipse.jetty.server.HttpOutput; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.util.ArrayUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.log.JavaUtilLog; import org.eclipse.jetty.util.resource.Resource; @@ -343,6 +344,8 @@ public void init(String appengineWebXmlFile) throws AppEngineConfigException, IO getSessionHandler().setSessionManager(sessionManager); VmRuntimeInterceptor.init(appEngineWebXml); + + setProtectedTargets(ArrayUtil.addToArray(getProtectedTargets(), "/app.yaml", String.class)); } @Override diff --git a/jetty9-compat-base/src/main/jetty-base/etc/gae.xml b/jetty9-compat-base/src/main/jetty-base/etc/gae.xml index 4f66077..cacb1ae 100644 --- a/jetty9-compat-base/src/main/jetty-base/etc/gae.xml +++ b/jetty9-compat-base/src/main/jetty-base/etc/gae.xml @@ -100,4 +100,8 @@ + + + + diff --git a/jetty9-compat-base/src/main/jetty-base/modules/gae.mod b/jetty9-compat-base/src/main/jetty-base/modules/gae.mod index 0d2f7ba..fe4cdb6 100644 --- a/jetty9-compat-base/src/main/jetty-base/modules/gae.mod +++ b/jetty9-compat-base/src/main/jetty-base/modules/gae.mod @@ -39,6 +39,7 @@ jetty.httpConfig.requestHeaderSize=8192 jetty.httpConfig.responseHeaderSize=8192 jetty.httpConfig.sendServerVersion=true jetty.httpConfig.sendDateHeader=false +jetty.server.stopTimeout=30000 jetty.server.dumpAfterStart=false jetty.server.dumpBeforeStop=false jetty.httpConfig.delayDispatchUntilContent=false diff --git a/jetty9-compat-base/src/test/java/com/google/apphosting/vmruntime/jetty9/VmRuntimeJettyKitchenSinkIT.java b/jetty9-compat-base/src/test/java/com/google/apphosting/vmruntime/jetty9/VmRuntimeJettyKitchenSinkIT.java index 34006e8..b2c80b7 100644 --- a/jetty9-compat-base/src/test/java/com/google/apphosting/vmruntime/jetty9/VmRuntimeJettyKitchenSinkIT.java +++ b/jetty9-compat-base/src/test/java/com/google/apphosting/vmruntime/jetty9/VmRuntimeJettyKitchenSinkIT.java @@ -90,6 +90,15 @@ public void testWelcomeServlet() throws Exception { assertTrue(Arrays.asList(lines).contains("Hello, World!")); } + /** + * Tests that app.yaml is protected + */ + public void testAppYamlHidden() throws Exception { + HttpURLConnection connection = (HttpURLConnection) createUrl("/app.yaml").openConnection(); + connection.connect(); + assertEquals(404, connection.getResponseCode()); + } + /** * Test that the API Proxy was configured by the VmRuntimeFilter. */ diff --git a/jetty9-compat/pom.xml b/jetty9-compat/pom.xml index 44355df..e2984c5 100644 --- a/jetty9-compat/pom.xml +++ b/jetty9-compat/pom.xml @@ -21,7 +21,7 @@ com.google.appengine appengine-java-vm-runtime - 1.9.38-SNAPSHOT + 1.9.40-SNAPSHOT ../pom.xml Google App Engine Image with GAE Compatibility (jetty9-compat) diff --git a/jetty9-compat/src/main/docker/Dockerfile b/jetty9-compat/src/main/docker/Dockerfile index 2250108..61e7446 100644 --- a/jetty9-compat/src/main/docker/Dockerfile +++ b/jetty9-compat/src/main/docker/Dockerfile @@ -29,7 +29,7 @@ ADD jetty-base jetty_run.sh $JETTY_BASE/ WORKDIR $JETTY_BASE RUN sed -i 's/^\([a-zA-Z\.]*=\).*/#\1(see gae.ini)/' start.d/server.ini \ && java -jar $JETTY_HOME/start.jar --dry-run \ - | sed 's/^.*java /& ${JAVA_OPTS} /' > jetty_cmd.sh \ + | sed 's/^.*java /exec & ${JAVA_OPTS} /' > jetty_cmd.sh \ && chown -R jetty:jetty $JETTY_BASE \ && chmod +x $JETTY_BASE/jetty_run.sh diff --git a/jetty9/pom.xml b/jetty9/pom.xml index a2ae674..ff27e63 100644 --- a/jetty9/pom.xml +++ b/jetty9/pom.xml @@ -21,7 +21,7 @@ com.google.appengine appengine-java-vm-runtime - 1.9.38-SNAPSHOT + 1.9.40-SNAPSHOT ../pom.xml Google App Engine Image Jetty (jetty9) diff --git a/openjdk8/pom.xml b/openjdk8/pom.xml index df762a5..29fd6da 100644 --- a/openjdk8/pom.xml +++ b/openjdk8/pom.xml @@ -21,7 +21,7 @@ com.google.appengine appengine-java-vm-runtime - 1.9.38-SNAPSHOT + 1.9.40-SNAPSHOT ../pom.xml Google App Engine Image for OpenJDK (openjdk8) diff --git a/pom.xml b/pom.xml index 88d4d15..df41792 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ com.google.appengine appengine-java-vm-runtime - 1.9.38-SNAPSHOT + 1.9.40-SNAPSHOT pom Google App Engine Runtime Parent @@ -34,7 +34,7 @@ UTF-8 yyyyMMddHHmm 9.3.8.v20160314 - 1.9.38 + 1.9.40 async- @@ -165,7 +165,6 @@ docker-maven-plugin 0.3.2 - org.apache.maven.plugins maven-surefire-plugin diff --git a/testwebapp/pom.xml b/testwebapp/pom.xml index 0c5da8e..6f63575 100644 --- a/testwebapp/pom.xml +++ b/testwebapp/pom.xml @@ -21,7 +21,7 @@ com.google.appengine appengine-java-vm-runtime - 1.9.38-SNAPSHOT + 1.9.40-SNAPSHOT ../pom.xml Compatibility test application diff --git a/testwebapp/src/main/webapp/app.yaml b/testwebapp/src/main/webapp/app.yaml new file mode 100644 index 0000000..27d5598 --- /dev/null +++ b/testwebapp/src/main/webapp/app.yaml @@ -0,0 +1 @@ +# dummy app.yaml \ No newline at end of file