From adb1c6f58ede0685a48399c0bf97b9fa98567c47 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Sun, 12 May 2019 18:14:55 +0000
Subject: [PATCH] Jetty: Fix webapps in eepsite (ticket #2477)

---
 apps/jetty/build.xml                          |  5 +-
 .../servlet/WebAppProviderConfiguration.java  | 58 +++++++++++++++++++
 debian-alt/disco/i2p-router.links             |  2 +
 debian-alt/jessie/i2p-router.links            |  2 +
 debian-alt/xenial/i2p-router.links            |  2 +
 debian/i2p-router.links                       |  3 +-
 installer/resources/eepsite/jetty.xml         | 22 ++++++-
 7 files changed, 90 insertions(+), 4 deletions(-)
 create mode 100644 apps/jetty/java/src/net/i2p/servlet/WebAppProviderConfiguration.java

diff --git a/apps/jetty/build.xml b/apps/jetty/build.xml
index ea28f52ce1..3135c1827c 100644
--- a/apps/jetty/build.xml
+++ b/apps/jetty/build.xml
@@ -366,12 +366,15 @@
             <classpath>
                 <pathelement location="../../../core/java/build/i2p.jar" />
                 <pathelement location="./jettylib/org.mortbay.jetty.jar" />
+                <pathelement location="./jettylib/jasper-runtime.jar" />
                 <pathelement location="./jettylib/javax.servlet.jar" />
+                <pathelement location="./jettylib/jetty-deploy.jar" />
                 <pathelement location="./jettylib/jetty-http.jar" />
                 <pathelement location="./jettylib/jetty-io.jar" />
                 <pathelement location="./jettylib/jetty-security.jar" />
                 <pathelement location="./jettylib/jetty-servlet.jar" />
                 <pathelement location="./jettylib/jetty-util.jar" />
+                <pathelement location="./jettylib/jetty-webapp.jar" />
                 <pathelement location="./jettylib/jetty-xml.jar" />
             </classpath>
         </depend>
@@ -385,7 +388,7 @@
             debug="true" deprecation="on" source="${javac.version}" target="${javac.version}" 
             destdir="./build/obj" 
             includeAntRuntime="false"
-            classpath="../../core/java/build/i2p.jar:./jettylib/javax.servlet.jar:./jettylib/org.mortbay.jetty.jar:./jettylib/jetty-http.jar:./jettylib/jetty-io.jar:./jettylib/jetty-security.jar:./jettylib/jetty-servlet.jar:./jettylib/jetty-util.jar:./jettylib/jetty-xml.jar" >
+            classpath="../../core/java/build/i2p.jar:./jettylib/javax.servlet.jar:./jettylib/org.mortbay.jetty.jar:./jettylib/jetty-http.jar:./jettylib/jetty-io.jar:./jettylib/jetty-security.jar:./jettylib/jetty-servlet.jar:./jettylib/jetty-util.jar:./jettylib/jetty-xml.jar:./jettylib/jetty-deploy.jar:./jettylib/jasper-runtime.jar:./jettylib/jetty-webapp.jar" >
             <compilerarg line="${javac.compilerargs}" />
         </javac>
     </target>
diff --git a/apps/jetty/java/src/net/i2p/servlet/WebAppProviderConfiguration.java b/apps/jetty/java/src/net/i2p/servlet/WebAppProviderConfiguration.java
new file mode 100644
index 0000000000..06eafd36df
--- /dev/null
+++ b/apps/jetty/java/src/net/i2p/servlet/WebAppProviderConfiguration.java
@@ -0,0 +1,58 @@
+package net.i2p.servlet;
+
+import org.apache.tomcat.SimpleInstanceManager;
+import org.eclipse.jetty.deploy.providers.WebAppProvider;
+import org.eclipse.jetty.webapp.Configuration;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+import net.i2p.I2PAppContext;
+
+/**
+ *  Work around the
+ *  "No org.apache.tomcat.InstanceManager set in ServletContext" problem
+ *  for eepsites with webapps.
+ *
+ *  See WebAppStarter and WebAppConfiguration for the console version.
+ *
+ *  @since 0.9.41
+ */
+public class WebAppProviderConfiguration {
+
+    /**
+     *  Modified from routerconsole WebAppStarter.
+     *  MUST be called from jetty.xml after the WebAppProvider is created.
+     */
+    public static void configure(WebAppProvider wap) {
+        String[] classNames = WebAppContext.getDefaultConfigurationClasses();
+        int sz = classNames.length;
+        String[] newClassNames = new String[sz + 1];
+        for (int j = 0; j < sz; j++) {
+            newClassNames[j] = classNames[j];
+        }
+        newClassNames[sz] = WAPConfiguration.class.getName();
+        wap.setConfigurationClasses(newClassNames);
+
+        // set the temp dir while we're at it,
+        // so the extracted wars don't end up in /tmp
+        wap.setTempDir(I2PAppContext.getGlobalContext().getTempDir());
+    }
+
+    public static class WAPConfiguration implements Configuration {
+
+        public void deconfigure(WebAppContext context) {}
+
+        public void configure(WebAppContext context) throws Exception {
+            // http://stackoverflow.com/questions/17529936/issues-while-using-jetty-embedded-to-handle-jsp-jasperexception-unable-to-com
+            // https://github.com/jetty-project/embedded-jetty-jsp/blob/master/src/main/java/org/eclipse/jetty/demo/Main.java
+            context.getServletContext().setAttribute("org.apache.tomcat.InstanceManager", new SimpleInstanceManager());
+        }
+
+        public void cloneConfigure(WebAppContext template, WebAppContext context) {}
+
+        public void destroy(WebAppContext context) {}
+
+        public void preConfigure(WebAppContext context) {}
+
+        public void postConfigure(WebAppContext context) {}
+    }
+}
diff --git a/debian-alt/disco/i2p-router.links b/debian-alt/disco/i2p-router.links
index 134d77543d..b01e00d4e5 100644
--- a/debian-alt/disco/i2p-router.links
+++ b/debian-alt/disco/i2p-router.links
@@ -48,6 +48,8 @@ usr/share/java/tomcat9-util-scan.jar usr/share/i2p/lib/tomcat-util-scan.jar
 usr/share/java/tomcat9-jasper-el.jar usr/share/i2p/lib/jasper-el.jar
 # legacy name in lib/
 usr/share/java/tomcat9-el-api.jar usr/share/i2p/lib/commons-el.jar
+# tomcat pulls in ecj, link to it for eepsite webapps needing a compiler
+usr/share/java/ecj.jar usr/share/i2p/lib/ecj.jar
 
 
 # comment out if not building with libtaglibs-standard
diff --git a/debian-alt/jessie/i2p-router.links b/debian-alt/jessie/i2p-router.links
index 131092a09b..7ab342e26a 100644
--- a/debian-alt/jessie/i2p-router.links
+++ b/debian-alt/jessie/i2p-router.links
@@ -48,6 +48,8 @@ usr/share/java/tomcat8-jasper-el.jar usr/share/i2p/lib/jasper-el.jar
 usr/share/java/tomcat8-el-api.jar usr/share/i2p/lib/commons-el.jar
 usr/share/java/tomcat8-servlet-api.jar usr/share/i2p/lib/javax.servlet.jar
 usr/share/java/tomcat8-jsp-api.jar usr/share/i2p/lib/jsp-api.jar
+# tomcat pulls in ecj, link to it for eepsite webapps needing a compiler
+usr/share/java/ecj.jar usr/share/i2p/lib/ecj.jar
 
 
 # comment out if not building with glassfish-javaee
diff --git a/debian-alt/xenial/i2p-router.links b/debian-alt/xenial/i2p-router.links
index e5ea1a5ad9..be8b765738 100644
--- a/debian-alt/xenial/i2p-router.links
+++ b/debian-alt/xenial/i2p-router.links
@@ -48,6 +48,8 @@ usr/share/java/tomcat8-util-scan.jar usr/share/i2p/lib/tomcat-util-scan.jar
 usr/share/java/tomcat8-jasper-el.jar usr/share/i2p/lib/jasper-el.jar
 # legacy name in lib/
 usr/share/java/tomcat8-el-api.jar usr/share/i2p/lib/commons-el.jar
+# tomcat pulls in ecj, link to it for eepsite webapps needing a compiler
+usr/share/java/ecj.jar usr/share/i2p/lib/ecj.jar
 
 
 # comment out if not building with glassfish-javaee
diff --git a/debian/i2p-router.links b/debian/i2p-router.links
index b2a5dbec98..91680fb9f4 100644
--- a/debian/i2p-router.links
+++ b/debian/i2p-router.links
@@ -48,7 +48,8 @@ usr/share/java/tomcat8-util-scan.jar usr/share/i2p/lib/tomcat-util-scan.jar
 usr/share/java/tomcat8-jasper-el.jar usr/share/i2p/lib/jasper-el.jar
 # legacy name in lib/
 usr/share/java/tomcat8-el-api.jar usr/share/i2p/lib/commons-el.jar
-
+# tomcat pulls in ecj, link to it for eepsite webapps needing a compiler
+usr/share/java/ecj.jar usr/share/i2p/lib/ecj.jar
 
 # comment out if not building with libtaglibs-standard
 usr/share/java/taglibs-standard-spec.jar usr/share/i2p/lib/jstl.jar
diff --git a/installer/resources/eepsite/jetty.xml b/installer/resources/eepsite/jetty.xml
index 294c3dbb36..d8d49157f3 100644
--- a/installer/resources/eepsite/jetty.xml
+++ b/installer/resources/eepsite/jetty.xml
@@ -235,16 +235,34 @@
     <Ref id="DeploymentManager">
       <Call id="webappprovider" name="addAppProvider">
         <Arg>
-          <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
+          <New id="WebAppProvider" class="org.eclipse.jetty.deploy.providers.WebAppProvider">
             <Set name="monitoredDirName">./eepsite/webapps</Set>
 	    <Set name="parentLoaderPriority">false</Set>
-	    <Set name="extractWars">false</Set>
+            <!-- this is required because Jetty can't handle jars inside wars,
+                 for example in php-java-bridge's JavaBridgeTemplate.war
+                 See https://bugs.eclipse.org/bugs/show_bug.cgi?id=433708
+                 See our ticket 2477
+              -->
+            <Set name="extractWars">true</Set>
             <Set name="defaultsDescriptor">./eepsite/etc/webdefault.xml</Set>
           </New>
         </Arg>
       </Call>
     </Ref>
 
+    <!-- Fixup for webapps to work, see our ticket 2477
+         Note that for webapps with uncompiled jsps, you will also
+         need a java compiler in the classpath;
+         The easiest way (Debian/Ubuntu) is to put a symlink in $I2P/lib:
+         sudo apt install libecj-java
+         cd $I2P/lib
+         ln -s /usr/share/java/ecj.jar
+         stop and then start i2p (restart alone will not pick up the new jar in the classpath)
+      -->
+    <Call class="net.i2p.servlet.WebAppProviderConfiguration" name="configure">
+      <Arg><Ref refid="WebAppProvider"/></Arg>
+    </Call>
+
     <!-- ===================== -->
     <!-- DefaultHandler config -->
     <!-- http://stackoverflow.com/questions/4202275/how-to-prevent-jetty-from-showing-context-related-information -->
-- 
GitLab