Changeset 34f0d7d7 for apps/jetty


Ignore:
Timestamp:
Sep 24, 2018 3:52:42 PM (2 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
39aa2c5
Parents:
e59d7a82
Message:

Build: Compile jsps in-order for reproducibility (ticket #2279)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • apps/jetty/java/src/net/i2p/servlet/util/JspC.java

    re59d7a82 r34f0d7d7  
    11package net.i2p.servlet.util;
    22
     3import java.io.File;
     4import java.io.InputStream;
     5import java.io.IOException;
    36import java.lang.reflect.Method;
     7import java.net.URL;
     8import java.util.Arrays;
     9import java.util.ArrayList;
     10import java.util.List;
     11import java.util.jar.Attributes;
     12import java.util.jar.Manifest;
     13
     14import net.i2p.util.FileSuffixFilter;
     15import net.i2p.util.VersionComparator;
    416
    517/**
     
    820 *  As of Tomcat 8.5.33, forking their JspC won't complete,
    921 *  because the JspC compilation is now threaded and the thread pool workers aren't daemons.
    10  *  May be fixed in a future release, maybe not, but we don't know what version distros may have.
     22 *  Will fixed in a 8.5.35, but we don't know what version distros may have.
     23 *
     24 *  Additionally, if the system property build.reproducible is "true",
     25 *  attempts to generate a reproducible build by compiling the
     26 *  jsps in order, for a consistent web.xml file.
    1127 *
    1228 *  https://tomcat.apache.org/tomcat-8.5-doc/changelog.html
    1329 *  https://bz.apache.org/bugzilla/show_bug.cgi?id=53492
     30 *  http://trac.i2p2.i2p/ticket/2307
     31 *  https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=908884
     32 *  https://bz.apache.org/bugzilla/show_bug.cgi?id=62674
    1433 *
    1534 *  We could set fork=false in build.xml, but then the paths are all wrong.
     
    2039 */
    2140public class JspC {
     41    // First Tomcat version to support multiple threads and -threadCount arg
     42    private static final String THREADS_VERSION = "8.5.33";
     43    // if true, try to make web.xml reproducible
     44    private static final boolean REPRODUCIBLE = Boolean.valueOf(System.getProperty("build.reproducible"));
     45    // if true, we must get the Tomcat version out of the jasper jar's manifest
     46    private static final boolean SYSTEM_TOMCAT = Boolean.valueOf(System.getProperty("with-libtomcat8-java"));
     47    // path to the jasper jar
     48    private static final String JASPER_JAR = System.getProperty("jasper.jar");
     49
     50    /**
     51     *  @throws IllegalArgumentException
     52     */
    2253    public static void main(String args[]) {
     54       if (REPRODUCIBLE)
     55           args = fixupArgs(args);
    2356       try {
    2457           String cls = "org.apache.jasper.JspC";
     
    3265       }
    3366    }
     67
     68    /**
     69     *  Only call this if we want reproducible builds.
     70     *
     71     *  Convert "-webapp dir/" arguments in the args to
     72     *  a sorted list of files, for reproducible builds.
     73     */
     74    private static String[] fixupArgs(String[] args) {
     75        List<String> largs = new ArrayList<String>(32);
     76
     77        // change the webapp arg to uriroot, save the location
     78        String sdir = null;
     79        for (int i = 0; i < args.length; i++) {
     80            String a = args[i];
     81            if (a.equals("-webapp")) {
     82                i++;
     83                if (i >= args.length)
     84                    throw new IllegalArgumentException("no value for -webapp");
     85                if (sdir != null)
     86                    throw new IllegalArgumentException("multiple -webapp args");
     87                sdir = args[i];
     88                largs.add("-uriroot");
     89                largs.add(sdir);
     90            } else {
     91                largs.add(a);
     92            }
     93        }
     94        if (sdir == null)
     95            return args;
     96        File dir = new File(sdir);
     97        if (!dir.exists())
     98            throw new IllegalArgumentException("webapp dir does not exist: " + sdir);
     99        if (!dir.isDirectory())
     100            throw new IllegalArgumentException("not a directory: " + sdir);
     101
     102        // If JspC supports the -threadCount argument, add it to force one thread.
     103        boolean supportsThreads = false;
     104        if (SYSTEM_TOMCAT) {
     105            if (JASPER_JAR != null) {
     106                // The JASPER_JAR property is a symlink to /usr/share/java/tomcat8-jasper.jar,
     107                // pull the version out of its manifest.
     108                Attributes atts = attributes(JASPER_JAR);
     109                if (atts != null) {
     110                    String ver = atts.getValue("Implementation-Version");
     111                    if (ver != null && ver.startsWith("8.")) {
     112                        supportsThreads = VersionComparator.comp(ver, THREADS_VERSION) >= 0;
     113                        System.out.println("Found JspC version: " + ver + ", supports threads? " + supportsThreads);
     114                    }
     115                }
     116            }
     117        } else {
     118            // We bundle 8.5.34+
     119            supportsThreads = true;
     120        }
     121        if (supportsThreads) {
     122            largs.add("-threadCount");
     123            largs.add("1");
     124        }
     125
     126        // add all the files as individual args
     127        File[] files = dir.listFiles(new FileSuffixFilter(".jsp"));
     128        if (files == null || files.length == 0)
     129            throw new IllegalArgumentException("no jsp files in webapp dir: " + sdir);
     130        Arrays.sort(files);
     131        for (int i = 0; i < files.length; i++) {
     132            largs.add(files[i].getName());
     133        }
     134        System.out.println("JspC arguments for reproducible build: " + largs);
     135        String[] rv = new String[largs.size()];
     136        rv = largs.toArray(rv);
     137        return rv;
     138    }
     139
     140    /**
     141     * jar manifest attributes
     142     * @return null if not found
     143     */
     144    private static Attributes attributes(String f) {
     145        InputStream in = null;
     146        try {
     147            in = (new URL("jar:file:" + f + "!/META-INF/MANIFEST.MF")).openStream();
     148            Manifest man = new Manifest(in);
     149            return man.getMainAttributes();
     150        } catch (IOException ioe) {
     151            return null;
     152        } finally {
     153            if (in != null) try { in.close(); } catch (IOException e) {}
     154        }
     155    }
    34156}
Note: See TracChangeset for help on using the changeset viewer.