changeset 1800:ffa10f8080d0

8189969: Manifest better manifest entries 8197030: Perf regression on all platforms with 8u171-b03 - early lambda use Reviewed-by: weijun, igerasim
author coffeys
date Mon, 15 Jan 2018 13:17:33 +0000
parents 299f966882e1
children 0ed664b26a02
files src/share/classes/sun/security/util/ManifestDigester.java test/javax/security/auth/Subject/doAs/NestedActions.java test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java test/lib/testlibrary/jdk/testlibrary/Utils.java
diffstat 4 files changed, 125 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/util/ManifestDigester.java	Fri Jan 05 20:11:29 2018 -0800
+++ b/src/share/classes/sun/security/util/ManifestDigester.java	Mon Jan 15 13:17:33 2018 +0000
@@ -26,8 +26,10 @@
 package sun.security.util;
 
 import java.security.*;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.io.ByteArrayOutputStream;
+import java.util.List;
 
 /**
  * This class is used to compute digests on sections of the Manifest.
@@ -39,7 +41,7 @@
     /** the raw bytes of the manifest */
     private byte rawBytes[];
 
-    /** the offset/length pair for a section */
+    /** the entries grouped by names */
     private HashMap<String, Entry> entries; // key is a UTF-8 string
 
     /** state returned by findSection */
@@ -120,8 +122,8 @@
             return; // XXX: exception?
 
         // create an entry for main attributes
-        entries.put(MF_MAIN_ATTRS,
-                new Entry(0, pos.endOfSection + 1, pos.startOfNext, rawBytes));
+        entries.put(MF_MAIN_ATTRS, new Entry().addSection(
+                new Section(0, pos.endOfSection + 1, pos.startOfNext, rawBytes)));
 
         int start = pos.startOfNext;
         while(findSection(start, pos)) {
@@ -167,9 +169,15 @@
                             }
                         }
 
-                        entries.put(nameBuf.toString(),
-                            new Entry(start, sectionLen, sectionLenWithBlank,
-                                rawBytes));
+                        Entry e = entries.get(nameBuf.toString());
+                        if (e == null) {
+                            entries.put(nameBuf.toString(), new Entry()
+                                .addSection(new Section(start, sectionLen,
+                                    sectionLenWithBlank, rawBytes)));
+                        } else {
+                            e.addSection(new Section(start, sectionLen,
+                                    sectionLenWithBlank, rawBytes));
+                        }
 
                     } catch (java.io.UnsupportedEncodingException uee) {
                         throw new IllegalStateException(
@@ -192,13 +200,52 @@
     }
 
     public static class Entry {
+
+        // One Entry for one name, and one name can have multiple sections.
+        // According to the JAR File Specification: "If there are multiple
+        // individual sections for the same file entry, the attributes in
+        // these sections are merged."
+        private List<Section> sections = new ArrayList<Section>();
+        boolean oldStyle;
+
+        private Entry addSection(Section sec)
+        {
+            sections.add(sec);
+            return this;
+        }
+
+        public byte[] digest(MessageDigest md)
+        {
+            md.reset();
+            for (Section sec : sections) {
+                if (oldStyle) {
+                    Section.doOldStyle(md, sec.rawBytes, sec.offset, sec.lengthWithBlankLine);
+                } else {
+                    md.update(sec.rawBytes, sec.offset, sec.lengthWithBlankLine);
+                }
+            }
+            return md.digest();
+        }
+
+        /** Netscape doesn't include the new line. Intel and JavaSoft do */
+
+        public byte[] digestWorkaround(MessageDigest md)
+        {
+            md.reset();
+            for (Section sec : sections) {
+                md.update(sec.rawBytes, sec.offset, sec.length);
+            }
+            return md.digest();
+        }
+    }
+
+    private static class Section {
         int offset;
         int length;
         int lengthWithBlankLine;
         byte[] rawBytes;
-        boolean oldStyle;
 
-        public Entry(int offset, int length,
+        public Section(int offset, int length,
                      int lengthWithBlankLine, byte[] rawBytes)
         {
             this.offset = offset;
@@ -207,18 +254,7 @@
             this.rawBytes = rawBytes;
         }
 
-        public byte[] digest(MessageDigest md)
-        {
-            md.reset();
-            if (oldStyle) {
-                doOldStyle(md,rawBytes, offset, lengthWithBlankLine);
-            } else {
-                md.update(rawBytes, offset, lengthWithBlankLine);
-            }
-            return md.digest();
-        }
-
-        private void doOldStyle(MessageDigest md,
+        private static void doOldStyle(MessageDigest md,
                                 byte[] bytes,
                                 int offset,
                                 int length)
@@ -242,16 +278,6 @@
             }
             md.update(bytes, start, i-start);
         }
-
-
-        /** Netscape doesn't include the new line. Intel and JavaSoft do */
-
-        public byte[] digestWorkaround(MessageDigest md)
-        {
-            md.reset();
-            md.update(rawBytes, offset, length);
-            return md.digest();
-        }
     }
 
     public Entry get(String name, boolean oldStyle) {
--- a/test/javax/security/auth/Subject/doAs/NestedActions.java	Fri Jan 05 20:11:29 2018 -0800
+++ b/test/javax/security/auth/Subject/doAs/NestedActions.java	Mon Jan 15 13:17:33 2018 +0000
@@ -23,7 +23,6 @@
  */
 
 import jdk.testlibrary.ProcessTools;
-import jdk.testlibrary.JarUtils;
 
 import javax.security.auth.Subject;
 import javax.security.auth.x500.X500Principal;
@@ -101,7 +100,7 @@
     public static void main(String[] args) throws IOException {
         if (args.length > 0) {
             if ("jar".equals(args[0]) && args.length > 2) {
-                JarUtils.createJar(args[1], Paths.get(TEST_CLASSES + FS),
+                createJar(args[1],
                     Arrays.copyOfRange(args, 2, args.length));
             } else {
                 runJava(args);
@@ -111,6 +110,21 @@
         }
     }
 
+    static void createJar(String dest, String... files) throws IOException {
+        System.out.println("Create " + dest + " with the following content:");
+        try (JarOutputStream jos = new JarOutputStream(
+                new FileOutputStream(dest), new Manifest())) {
+            for (String file : files) {
+                System.out.println("  " + file);
+                jos.putNextEntry(new JarEntry(file));
+                try (FileInputStream fis = new FileInputStream(
+                        TEST_CLASSES + FS + file)) {
+                    jdk.testlibrary.Utils.transferTo(fis, jos);
+                }
+            }
+        }
+    }
+
     static void runJava(String[] args) {
         if (args == null || args.length < 3) {
             throw new IllegalArgumentException("wrong parameters");
--- a/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java	Fri Jan 05 20:11:29 2018 -0800
+++ b/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java	Mon Jan 15 13:17:33 2018 +0000
@@ -362,6 +362,21 @@
     }
 
     /**
+     * Verify the exit value of the process
+     *
+     * @param notExpectedExitValue Unexpected exit value from process
+     * @throws RuntimeException If the exit value from the process did match the expected value
+     */
+    public OutputAnalyzer shouldNotHaveExitValue(int notExpectedExitValue) {
+        if (getExitValue() == notExpectedExitValue) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("Unexpected to get exit value of ["
+                    + notExpectedExitValue + "]\n");
+        }
+        return this;
+    }
+
+    /**
      * Report summary that will help to diagnose the problem Currently includes:
      * - standard input produced by the process under test - standard output -
      * exit code Note: the command line is printed by the ProcessTools
--- a/test/lib/testlibrary/jdk/testlibrary/Utils.java	Fri Jan 05 20:11:29 2018 -0800
+++ b/test/lib/testlibrary/jdk/testlibrary/Utils.java	Mon Jan 15 13:17:33 2018 +0000
@@ -56,6 +56,9 @@
     public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim();
 
 
+    private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
+    private static final int DEFAULT_BUFFER_SIZE = 8192;
+
     private Utils() {
         // Private constructor to prevent class instantiation
     }
@@ -232,6 +235,40 @@
     private static final int BUFFER_SIZE = 1024;
 
     /**
+     * Helper method to read all bytes from InputStream
+     *
+     * @param is InputStream to read from
+     * @return array of bytes
+     * @throws IOException
+     */
+    public static byte[] readAllBytes(InputStream is) throws IOException {
+        byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
+        int capacity = buf.length;
+        int nread = 0;
+        int n;
+        for (;;) {
+            // read to EOF which may read more or less than initial buffer size
+            while ((n = is.read(buf, nread, capacity - nread)) > 0)
+                nread += n;
+
+            // if the last call to read returned -1, then we're done
+            if (n < 0)
+                break;
+
+            // need to allocate a larger buffer
+            if (capacity <= MAX_BUFFER_SIZE - capacity) {
+                capacity = capacity << 1;
+            } else {
+                if (capacity == MAX_BUFFER_SIZE)
+                    throw new OutOfMemoryError("Required array size too large");
+                capacity = MAX_BUFFER_SIZE;
+            }
+            buf = Arrays.copyOf(buf, capacity);
+        }
+        return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
+    }
+
+    /**
      * Reads all bytes from the input stream and writes the bytes to the
      * given output stream in the order that they are read. On return, the
      * input stream will be at end of stream. This method does not close either
@@ -256,7 +293,7 @@
      * @throws NullPointerException if {@code in} or {@code out} is {@code null}
      *
      */
-    public static long transferBetweenStreams(InputStream in, OutputStream out)
+    public static long transferTo(InputStream in, OutputStream out)
             throws IOException  {
         long transferred = 0;
         byte[] buffer = new byte[BUFFER_SIZE];