diff --git a/apps/addressbook/build.gradle b/apps/addressbook/build.gradle index 184c59c9a..17e5ed8f0 100644 --- a/apps/addressbook/build.gradle +++ b/apps/addressbook/build.gradle @@ -1,3 +1,5 @@ +apply plugin:'war' + sourceSets { main { java { @@ -7,6 +9,14 @@ sourceSets { } dependencies { - compile project(':core') - compile project(':apps:jetty') + providedCompile project(':core') + providedCompile project(':apps:jetty') +} + +war { + rootSpec.exclude('**/*.class') +} + +artifacts { + archives war } diff --git a/apps/i2pcontrol/build.gradle b/apps/i2pcontrol/build.gradle index a8c1173e3..79da21623 100644 --- a/apps/i2pcontrol/build.gradle +++ b/apps/i2pcontrol/build.gradle @@ -20,3 +20,7 @@ war { archiveName 'jsonrpc.war' webXml = file('web.xml') } + +artifacts { + archives war +} diff --git a/apps/i2psnark/build.gradle b/apps/i2psnark/build.gradle index 7f3bd5b34..01e676e72 100644 --- a/apps/i2psnark/build.gradle +++ b/apps/i2psnark/build.gradle @@ -32,7 +32,7 @@ task i2psnarkJar(type: Jar) { // TODO: standalone jar. This is rather involved! artifacts { - archives i2psnarkJar + archives i2psnarkJar,war } // Create the java files from the po files. The jar task will compile them. diff --git a/apps/i2ptunnel/build.gradle b/apps/i2ptunnel/build.gradle index 23f73e017..fd5c8e536 100644 --- a/apps/i2ptunnel/build.gradle +++ b/apps/i2ptunnel/build.gradle @@ -22,6 +22,9 @@ dependencies { providedCompile project(':apps:ministreaming') compile 'gnu.getopt:java-getopt:1.0.13' providedCompile project(':apps:jetty') + + implementation 'org.apache.ant:ant:1.10.10' + implementation fileTree("../jetty/apache-tomacat-${tomcatVersion}") } // Create the java files from the po files. The jar task will compile them. @@ -62,8 +65,73 @@ task i2ptunnelJar(type: Jar) { into "net/i2p/i2ptunnel/resources" }) } + +task helpersJar(type: Jar) { + from sourceSets.main.output + include '**/EditBean.class' + include '**/IndexBean.class' + include 'net/i2p/i2ptunnel/ui/**' + include 'net/i2p/i2ptunnel/web/SSLHelper.class' + archiveBaseName='i2pTunnelHelpers' +} + +task precompileJsp(type : JavaExec) { + classpath = sourceSets.main.runtimeClasspath + main = 'net.i2p.servlet.util.JspC' + + jvmArgs "-Dtomcat.util.scan.StandardJarScanFilter.jarsToSkip=commons-collections.jar,junit.jar,junit4.jar" + jvmArgs "-Dbuild.reproducible=true" + + args "-d" + args "jsp/WEB-INF/classes" + args "-v" + args "-p" + args "net.i2p.i2ptunnel.jsp" + args "-webinc" + args "$buildDir/web-fragment.xml" + args "-webapp" + args "jsp" + doLast { + def output = new File("$buildDir/compiledJsps") + output.mkdirs() + ant.javac(srcDir: "jsp/WEB-INF/classes", + classpath: sourceSets.main.runtimeClasspath.asPath, + debug : true, + includeAntRuntime : false, + deprecation : "on", + source: project.sourceCompatibility, + target: project.targetCompatibility, + destDir:file("$buildDir/compiledJsps")) + + def fragment = file("$buildDir/web-fragment.xml").text + def templateXML = file("jsp/web.xml").text + def webXML = templateXML.replace("", fragment) + + def multipart = "" + + "134217728" + + "134217728" + + "262144" + + "" + + def multipartServlets = ["register"] + + + multipartServlets = multipartServlets.collect { + "net.i2p.i2ptunnel.jsp.${it}_jsp" + } + + multipartServlets.each { + webXML = webXML.replace(it, it + multipart) + } + + file("$buildDir/web.xml").text = webXML + } + + +} + i2ptunnelJar.dependsOn bundleProxy -war.dependsOn bundle +war.dependsOn bundle,precompileJsp // not needed unless we're building for both android and regular task tempBeansJar(type: Jar) { @@ -85,7 +153,7 @@ task uiJar(type: Jar) { } artifacts { - archives i2ptunnelJar //, tempBeansJar, uiJar + archives i2ptunnelJar,war //, tempBeansJar, uiJar } war { @@ -93,6 +161,11 @@ war { include '**/ui/*.class' include '**/IndexBean.class' from 'jsp' + from ("$buildDir/compiledJsps") { + include '**/*.class' + into "WEB-INF/classes" + } + rootSpec.exclude('**/*.jar') rootSpec.exclude('/net/i2p/i2ptunnel/*.class') rootSpec.exclude('/net/i2p/i2ptunnel/access') rootSpec.exclude('/net/i2p/i2ptunnel/irc') @@ -102,9 +175,11 @@ war { rootSpec.exclude('/net/i2p/i2ptunnel/streamr') rootSpec.exclude('/net/i2p/i2ptunnel/udp') rootSpec.exclude('/net/i2p/i2ptunnel/udpTunnel') - exclude 'jsp/web.xml' - exclude '*.jsi' - exclude '*.jsp' - webXml = file('jsp/web.xml') + from("jsp") { + exclude 'web.xml' + exclude '*.jsi' + exclude '*.jsp' + } + webXml = file("$buildDir/web.xml") } diff --git a/apps/imagegen/build.gradle b/apps/imagegen/build.gradle index 8ee45832a..a55972a73 100644 --- a/apps/imagegen/build.gradle +++ b/apps/imagegen/build.gradle @@ -14,7 +14,7 @@ sourceSets { } dependencies { - compile project(':core') + providedCompile project(':core') providedCompile project(':apps:jetty') } @@ -23,3 +23,7 @@ war { from 'imagegen/webapp/src/main/webapp/index.html' webXml = file('imagegen/webapp/src/main/webapp/WEB-INF/web.xml') } + +artifacts { + archives war +} diff --git a/apps/jetty/build.gradle b/apps/jetty/build.gradle index f830a6a67..1c17c5efd 100644 --- a/apps/jetty/build.gradle +++ b/apps/jetty/build.gradle @@ -10,7 +10,7 @@ sourceSets { dependencies { ext.jettyVersion = '9.3.29.v20201019' - ext.tomcatVersion = '9.0.40' + ext.tomcatVersion = "${tomcatVersion}" compile project(':core') compile 'org.eclipse.jetty:jetty-http:' + ext.jettyVersion compile 'org.eclipse.jetty:jetty-io:' + ext.jettyVersion diff --git a/apps/routerconsole/build.gradle b/apps/routerconsole/build.gradle index a18c1e54d..60bad6e0e 100644 --- a/apps/routerconsole/build.gradle +++ b/apps/routerconsole/build.gradle @@ -18,11 +18,15 @@ dependencies { compile project(':core') compile project(':router') compile project(':installer') + + // below were providedCompile providedCompile project(':apps:desktopgui') providedCompile project(':apps:systray') providedCompile project(':apps:jetty') providedCompile project(':apps:jrobin') + implementation 'org.apache.ant:ant:1.10.10' + implementation fileTree("../jetty/apache-tomacat-${tomcatVersion}") testCompile "org.scala-lang:scala-library:2.12.4" testCompile 'org.scalatest:scalatest_2.12:3.0.4' } @@ -77,26 +81,96 @@ task consoleJar(type: Jar) { into "net/i2p/router/news/resources" }) } -consoleJar.dependsOn bundleJar -war.dependsOn bundle -artifacts { - archives consoleJar +task helpersJar(type: Jar) { + from sourceSets.main.output + include 'net/i2p/router/web/helpers/**' + archiveBaseName = 'consoleHelpers' } + +task precompileJsp(type: JavaExec) { + classpath = sourceSets.main.runtimeClasspath + main = 'net.i2p.servlet.util.JspC' + + jvmArgs "-Dtomcat.util.scan.StandardJarScanFilter.jarsToSkip=commons-collections.jar,junit.jar,junit4.jar" + jvmArgs "-Dbuild.reproducible=true" + + args "-d" + args "jsp/WEB-INF/classes" + args "-v" + args "-p" + args "net.i2p.router.web.jsp" + args "-webinc" + args "$buildDir/web-fragment.xml" + args "-webapp" + args "jsp" + doLast { + def output = new File("$buildDir/compiledJsps") + output.mkdirs() + ant.javac(srcDir: "jsp/WEB-INF/classes", + classpath: sourceSets.main.runtimeClasspath.asPath, + debug : true, + includeAntRuntime : false, + deprecation : "on", + source: project.sourceCompatibility, + target: project.targetCompatibility, + destDir:file("$buildDir/compiledJsps")) + + def fragment = file("$buildDir/web-fragment.xml").text + def templateXML = file("jsp/web.xml").text + def webXML = templateXML.replace("", fragment) + + def multipart = "" + + "134217728" + + "134217728" + + "262144" + + "" + + def multipartServlets = ["configplugins", + "configfamily", + "configreseed"] + + multipartServlets = multipartServlets.collect { + "net.i2p.router.web.jsp.${it}_jsp" + } + + multipartServlets.each { + webXML = webXML.replace(it, it + multipart) + } + + file("$buildDir/web.xml").text = webXML + } + +} + +consoleJar.dependsOn bundleJar +war.dependsOn(bundle,precompileJsp) + + war { + rootSpec.exclude('**/*.jar') rootSpec.exclude('/com/vuze/**/*') rootSpec.exclude('/edu/internet2/**/*') rootSpec.exclude('/net/i2p/router/news/*') rootSpec.exclude('/net/i2p/router/sybil/*') rootSpec.exclude('/net/i2p/router/update/*') rootSpec.exclude('/net/i2p/router/web/*.class') - from 'jsp' - exclude 'jsp/web.xml' - exclude '*.jsi' - exclude '*.jsp' - webXml = file('jsp/web.xml') + from ("$buildDir/compiledJsps") { + into "WEB-INF/classes" + } + from ('jsp') { + exclude 'web.xml' + exclude '*.jsi' + exclude '*.jsp' + } + webXml = file("$buildDir/web.xml") from ('resources', { into "WEB-INF/classes/net/i2p/router/web/resources" }) } + +artifacts { + archives war,consoleJar +} + diff --git a/apps/susidns/build.gradle b/apps/susidns/build.gradle index 254f7c039..9939f4124 100644 --- a/apps/susidns/build.gradle +++ b/apps/susidns/build.gradle @@ -12,8 +12,11 @@ sourceSets { } dependencies { - compile project(':core') + providedCompile project(':core') providedCompile project(':apps:jetty') + + implementation 'org.apache.ant:ant:1.10.10' + implementation fileTree("../jetty/apache-tomacat-${tomcatVersion}") } // Create the java files from the po files. The jar task will compile them. @@ -25,9 +28,84 @@ task bundle { println "apps/susidns/src/bundle-messages.sh".execute().text } } -war.dependsOn bundle + +task precompileJsp(type: JavaExec) { + doFirst { + file("$buildDir/tmp_jsp").mkdirs() + } + + classpath = sourceSets.main.runtimeClasspath + fileTree("src/lib") + main = 'net.i2p.servlet.util.JspC' + + jvmArgs "-Dtomcat.util.scan.StandardJarScanFilter.jarsToSkip=commons-collections.jar,junit.jar,junit4.jar" + jvmArgs "-Dbuild.reproducible=true" + + args "-d" + args "$buildDir/tmp_jsp" + args "-v" + args "-p" + args "i2p.susi.dns.jsp" + args "-webinc" + args "$buildDir/web-fragment.xml" + args "-webapp" + args "src/jsp" + doLast { + // normalize the order of the _jspx_dependents + ant.replaceregexp(file : "$buildDir/tmp_jsp/i2p/susi/dns/jsp/addressbook_jsp.java", + match : "_jspx_dependants.put\\(.*\\);", + replace : "//_jspx_dependants.put(@@@);", + flags : "g") + ant.replaceregexp(file : "$buildDir/tmp_jsp/i2p/susi/dns/jsp/addressbook_jsp.java", + match : "//_jspx_dependants.put(@@@);", + replace : "_jspx_dependants.put("jar:file:lib/standard.jar!/META-INF/c.tld", Long.valueOf(1200000000000L));") + ant.replaceregexp(file : "$buildDir/tmp_jsp/i2p/susi/dns/jsp/addressbook_jsp.java", + match : "//_jspx_dependants.put(@@@);", + replace : "_jspx_dependants.put("file:lib/standard.jar", Long.valueOf(1200000000000L));") + + def output = new File("$buildDir/compiledJsps") + output.mkdirs() + + def classpath = sourceSets.main.runtimeClasspath + fileTree("src/lib") + + ant.javac(srcDir: "$buildDir/tmp_jsp", + classpath: classpath.asPath, + debug : true, + includeAntRuntime : false, + deprecation : "on", + source: project.sourceCompatibility, + target: project.targetCompatibility, + destDir:file("$buildDir/compiledJsps")) + + def fragment = file("$buildDir/web-fragment.xml").text + def templateXML = file("src/WEB-INF/web-template.xml").text + def webXML = templateXML.replace("", fragment) + + def multipart = "" + + "134217728" + + "134217728" + + "262144" + + "" + + def multipartServlets = ["addressbook"] + + multipartServlets = multipartServlets.collect { + "net.i2p.router.web.jsp.${it}_jsp" + } + + multipartServlets.each { + webXML = webXML.replace(it, it + multipart) + } + + file("$buildDir/web.xml").text = webXML + + + } +} + +war.dependsOn bundle,precompileJsp war { + rootSpec.exclude("**/*.jar") from 'src/jsp' from 'src/index.html' from ('src/js', { @@ -39,7 +117,16 @@ war { from ('src/themes', { into "themes" }) + from ("$buildDir/compiledJsps") { + include '**/*.class' + into 'WEB-INF/classes' + } exclude '*.jsi' exclude '*.jsp' - webXml = file('src/WEB-INF/web-template.xml') + webXml = file("$buildDir/web.xml") } + +artifacts { + archives war +} + diff --git a/apps/susimail/build.gradle b/apps/susimail/build.gradle index e9f9cf8fd..56c6ec64a 100644 --- a/apps/susimail/build.gradle +++ b/apps/susimail/build.gradle @@ -39,3 +39,7 @@ war { } webXml = file('src/WEB-INF/web.xml') } + +artifacts { + archives war +} diff --git a/apps/systray/build.gradle b/apps/systray/build.gradle index 035b394f0..5efcf77b9 100644 --- a/apps/systray/build.gradle +++ b/apps/systray/build.gradle @@ -8,5 +8,4 @@ sourceSets { dependencies { compile project(':core') - compile files('java/lib/systray4j.jar') } diff --git a/build.gradle b/build.gradle index b6288f07f..1adf0fd2f 100644 --- a/build.gradle +++ b/build.gradle @@ -53,6 +53,7 @@ String getWorkspaceVersion() { "git" // TODO: extract revision } + def releaseVersion = getReleaseVersion() def buildVersion = getBuildVersion() def buildExtra = getBuildExtra() @@ -75,6 +76,8 @@ subprojects { testCompile 'org.mockito:mockito-core:2.5.0' } + + sourceCompatibility = 1.8 targetCompatibility = 1.8 @@ -100,6 +103,9 @@ subprojects { tasks.withType(AbstractArchiveTask) { preserveFileTimestamps = false reproducibleFileOrder = true + doLast { + stripJar(it.archivePath) + } } } @@ -125,3 +131,23 @@ task codeCoverageReport(type: JacocoReport) { } apply from: file('gradle/update.gradle') + +import java.util.jar.* +void stripJar(File file) { + if (file.getName().endsWith('.tar')) + return + println "stripping $file" + File newFile = new File(file.parent, 'tmp-' + file.name) + newFile.withOutputStream { fout -> + JarOutputStream out = new JarOutputStream(fout) + JarFile jf = new JarFile(file) + jf.entries().unique {it.name}.sort {it.name}.each { + def copy = new JarEntry(it.name) + copy.time = 1001 + out.putNextEntry(copy) + out << jf.getInputStream(it) + } + out.finish() + } + newFile.renameTo file +} diff --git a/gradle.properties b/gradle.properties index de9bef337..e723f748d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,3 @@ # Override these in ~/.gradle/gradle.properties if necessary java7BootClasspath= +tomcatVersion=9.0.45 diff --git a/reproducible/build.gradle b/reproducible/build.gradle new file mode 100644 index 000000000..27c92d19c --- /dev/null +++ b/reproducible/build.gradle @@ -0,0 +1,93 @@ +apply plugin: 'application' + +application { + mainClassName='net.i2p.router.RouterLaunch' + applicationName='i2p' +} + +dependencies { + implementation project(':router') + implementation project(':apps:ministreaming') + implementation project(':apps:streaming') + implementation project(':apps:i2ptunnel') + implementation project(':apps:jetty') + implementation project(':apps:i2psnark') + implementation project(':apps:systray') + implementation project(':apps:BOB') + implementation project(':apps:sam') + implementation project(':apps:routerconsole') + implementation project(':apps:desktopgui') + implementation project(':apps:jrobin') + implementation project(':apps:addressbook') + implementation project(':apps:susidns') + implementation project(':apps:susimail') + implementation project(':apps:i2pcontrol') + implementation project(':apps:imagegen') + implementation project(':core') + implementation project(':router') + implementation project(path : ':installer', configuration: 'jbigi') + implementation fileTree("../apps/susidns/src/lib") +} + +import java.nio.file.* +import java.util.zip.* + +def projects = [':apps:routerconsole', + ':apps:addressbook', + ':apps:i2psnark', + ':apps:imagegen', + ':apps:i2pcontrol', + ':apps:susidns', + ':apps:susimail', + ':apps:i2ptunnel'].collect {project(it)} + +def rootDir = project.getRootProject().getRootDir() +def buildDir = new File("$buildDir") +def webappDir = new File(buildDir, 'webapps') +def geoipDir = new File(buildDir, "geoip") + +task copyWars { + doLast { + webappDir.mkdirs() + projects.each { p -> + p.configurations.archives.getArtifacts().getFiles(). + filter({it.getName().endsWith('war')}).each { file -> + println "copying war $file exists ${file.exists()}" + File target = new File(webappDir, file.getName()) + Files.copy(file.toPath(), target.toPath()) + } + } + } +} + +projects.each { p -> + copyWars.dependsOn p.tasks['assemble'] +} + +task copyGeoip() { + doLast { + geoipDir.mkdirs() + File target = new File(geoipDir, "GeoLite2-Country.mmdb") + File source = new File("$rootDir/installer/resources/GeoLite2-Country.mmdb.gz") + InputStream is = new GZIPInputStream(new FileInputStream(source)) + java.nio.file.Files.copy(is, target.toPath()) + } +} + +jar.dependsOn copyWars,copyGeoip + +distributions { + main { + contents { + from('../installer/resources/') { + exclude '*.gz*' + } + from(webappDir.getAbsolutePath()) { + into 'webapps' + } + from(geoipDir.getAbsolutePath()) { + into 'geoip' + } + } + } +} diff --git a/settings.gradle b/settings.gradle index 281bf7e32..cb82c6720 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,3 +17,4 @@ include 'apps:imagegen' include 'core' include 'installer' include 'router' +include 'reproducible'