1 /*
   2  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug 6434207 6442687 6984046
  27  * @modules jdk.jartool
  28  * @summary Ensure that jar ufm actually updates the
  29  * existing jar file's manifest with contents of the
  30  * manifest file.
  31  */
  32 
  33 import java.io.*;
  34 import java.util.logging.*;
  35 import java.util.spi.ToolProvider;
  36 import java.util.zip.*;
  37 
  38 public class UpdateManifest {
  39     static PrintStream out = System.out;
  40     static PrintStream err = System.err;
  41     static boolean debug = true;
  42 
  43     static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar").get();
  44 
  45     static final Logger JAR_LOGGER = Logger.getLogger("java.util.jar");
  46 
  47     public static void realMain(String[] args) throws Throwable {
  48         if (args.length == 0) {
  49             debug = false;
  50             File tmp = File.createTempFile("system-out-err", ".txt");
  51             tmp.deleteOnExit();
  52             out = new PrintStream(new FileOutputStream(tmp));
  53             err = out;
  54             // Attributes.read() can log a message we don't care to see.
  55             JAR_LOGGER.setLevel(Level.OFF);
  56         }
  57 
  58         try { testManifestExistence(); } catch (Throwable t) { unexpected(t); }
  59         try { testManifestContents(); } catch (Throwable t) { unexpected(t); }
  60     }
  61 
  62     static void testManifestExistence() throws Throwable {
  63         // Create a file to put in a jar file
  64         File existence = createTextFile("existence");
  65 
  66         // Create a jar file, specifying a Main-Class
  67         final String jarFileName = "um-existence.jar";
  68         new File(jarFileName).delete(); // remove pre-existing first!
  69         int status = JAR_TOOL.run(out, err, "cfe", jarFileName,
  70                                   "Hello", existence.getPath());
  71         check(status == 0);
  72         checkManifest(jarFileName, "Hello");
  73 
  74         // Update that jar file by changing the Main-Class
  75         status = JAR_TOOL.run(out, err, "ufe", jarFileName, "Bye");
  76         check(status == 0);
  77         checkManifest(jarFileName, "Bye");
  78     }
  79 
  80     static void testManifestContents() throws Throwable {
  81         // Create some strings we expect to find in the updated manifest
  82         final String animal =
  83             "Name: animal/marsupial";
  84         final String specTitle =
  85             "Specification-Title: Wombat";
  86 
  87         // Create a text file with manifest entries
  88         File manifestOrig = File.createTempFile("manifestOrig", ".txt");
  89         if (!debug) manifestOrig.deleteOnExit();
  90         PrintWriter pw = new PrintWriter(manifestOrig);
  91         pw.println("Manifest-Version: 1.0");
  92         pw.println("Created-By: 1.7.0-internal (Oracle Corporation)");
  93         pw.println("");
  94         pw.println(animal);
  95         pw.println(specTitle);
  96         pw.close();
  97 
  98         File hello = createTextFile("hello");
  99 
 100         // Create a jar file
 101         final String jarFileName = "um-test.jar";
 102         new File(jarFileName).delete(); // remove pre-existing first!
 103         int status = JAR_TOOL.run(out, err, "cfm", jarFileName,
 104                                   manifestOrig.getPath(), hello.getPath());
 105         check(status == 0);
 106 
 107         // Create a new manifest, to use in updating the jar file.
 108         File manifestUpdate = File.createTempFile("manifestUpdate", ".txt");
 109         if (!debug) manifestUpdate.deleteOnExit();
 110         pw = new PrintWriter(manifestUpdate);
 111         final String createdBy =
 112             "Created-By: 1.7.0-special (Oracle Corporation)";
 113         final String specVersion =
 114             "Specification-Version: 1.0.0.0";
 115         pw.println(createdBy); // replaces line in the original
 116         pw.println("");
 117         pw.println(animal);
 118         pw.println(specVersion); // addition to animal/marsupial section
 119         pw.close();
 120 
 121         // Update jar file with manifest
 122         status = JAR_TOOL.run(out, err, "ufm",
 123                               jarFileName, manifestUpdate.getPath());
 124         check(status == 0);
 125 
 126         // Extract jar, and verify contents of manifest file
 127         File f = new File(jarFileName);
 128         if (!debug) f.deleteOnExit();
 129         ZipFile zf = new ZipFile(f);
 130         ZipEntry ze = zf.getEntry("META-INF/MANIFEST.MF");
 131         BufferedReader r = new BufferedReader(
 132             new InputStreamReader(zf.getInputStream(ze)));
 133         r.readLine(); // skip Manifest-Version
 134         check(r.readLine().equals(createdBy));
 135         r.readLine(); // skip blank line
 136         check(r.readLine().equals(animal));
 137         String s = r.readLine();
 138         if (s.equals(specVersion)) {
 139             check(r.readLine().equals(specTitle));
 140         } else if (s.equals(specTitle)) {
 141             check(r.readLine().equals(specVersion));
 142         } else {
 143             fail("did not match specVersion nor specTitle");
 144         }
 145         zf.close();
 146     }
 147 
 148     // --------------------- Convenience ---------------------------
 149 
 150     static File createTextFile(String name) throws Throwable {
 151         // Create a text file to put in a jar file
 152         File rc = File.createTempFile(name, ".txt");
 153         if (!debug) rc.deleteOnExit();
 154         PrintWriter pw = new PrintWriter(rc);
 155         pw.println("hello, world");
 156         pw.close();
 157         return rc;
 158     }
 159 
 160     static void checkManifest(String jarFileName, String mainClass)
 161                 throws Throwable {
 162         File f = new File(jarFileName);
 163         if (!debug) f.deleteOnExit();
 164         ZipFile zf = new ZipFile(f);
 165         ZipEntry ze = zf.getEntry("META-INF/MANIFEST.MF");
 166         BufferedReader r = new BufferedReader(
 167             new InputStreamReader(zf.getInputStream(ze)));
 168         String line = r.readLine();
 169         while (line != null && !(line.startsWith("Main-Class:"))) {
 170             line = r.readLine();
 171         }
 172         if (line == null) {
 173             fail("Didn't find Main-Class in manifest");
 174         } else {
 175             check(line.equals("Main-Class: " + mainClass));
 176         }
 177         zf.close();
 178     }
 179 
 180     // --------------------- Infrastructure ---------------------------
 181 
 182     static volatile int passed = 0, failed = 0;
 183 
 184     static void pass() {
 185         passed++;
 186     }
 187 
 188     static void fail() {
 189         failed++;
 190         Thread.dumpStack();
 191     }
 192 
 193     static void fail(String msg) {
 194         System.out.println(msg);
 195         fail();
 196     }
 197 
 198     static void unexpected(Throwable t) {
 199         failed++;
 200         t.printStackTrace();
 201     }
 202 
 203     static void check(boolean cond) {
 204         if (cond)
 205             pass();
 206         else
 207             fail();
 208     }
 209 
 210     static void equal(Object x, Object y) {
 211         if ((x == null) ? (y == null) : x.equals(y))
 212             pass();
 213         else
 214             fail(x + " not equal to " + y);
 215     }
 216 
 217     public static void main(String[] args) throws Throwable {
 218         try {
 219             realMain(args);
 220         } catch (Throwable t) {
 221             unexpected(t);
 222         }
 223         System.out.println("\nPassed = " + passed + " failed = " + failed);
 224         if (failed > 0)
 225             throw new AssertionError("Some tests failed");
 226     }
 227 }