1 /*
   2  * Copyright (c) 2006, 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
  27  * @summary Ensure that jar ufm actually updates the
  28  * existing jar file's manifest with contents of the
  29  * manifest file.
  30  */
  31 
  32 import java.io.*;
  33 import java.util.logging.*;
  34 import java.util.zip.*;
  35 import sun.tools.jar.Main;
  36 
  37 public class UpdateManifest {
  38     static PrintStream out = System.out;
  39     static PrintStream err = System.err;
  40     static boolean debug = true;
  41 
  42     public static void realMain(String[] args) throws Throwable {
  43         if (args.length == 0) {
  44             debug = false;
  45             File tmp = File.createTempFile("system-out-err", ".txt");
  46             tmp.deleteOnExit();
  47             out = new PrintStream(new FileOutputStream(tmp));
  48             err = out;
  49             // Attributes.read() can log a message we don't care to see.
  50             Logger.getLogger("java.util.jar").setLevel(Level.OFF);
  51         }
  52 
  53         try { testManifestExistence(); } catch (Throwable t) { unexpected(t); }
  54         try { testManifestContents(); } catch (Throwable t) { unexpected(t); }
  55     }
  56 
  57     static void testManifestExistence() throws Throwable {
  58         // Create a file to put in a jar file
  59         File existence = createTextFile("existence");
  60 
  61         // Create a jar file, specifying a Main-Class
  62         final String jarFileName = "um-existence.jar";
  63         new File(jarFileName).delete(); // remove pre-existing first!
  64         Main jartool = new Main(out, err, "jar");
  65         boolean status = jartool.run(
  66             new String[] { "cfe", jarFileName, "Hello", existence.getPath() });
  67         check(status);
  68         checkManifest(jarFileName, "Hello");
  69 
  70         // Update that jar file by changing the Main-Class
  71         jartool = new Main(out, err, "jar");
  72         status = jartool.run(
  73             new String[] { "ufe", jarFileName, "Bye" });
  74         check(status);
  75         checkManifest(jarFileName, "Bye");
  76     }
  77 
  78     static void testManifestContents() throws Throwable {
  79         // Create some strings we expect to find in the updated manifest
  80         final String animal =
  81             "Name: animal/marsupial";
  82         final String specTitle =
  83             "Specification-Title: Wombat";
  84 
  85         // Create a text file with manifest entries
  86         File manifestOrig = File.createTempFile("manifestOrig", ".txt");
  87         if (!debug) manifestOrig.deleteOnExit();
  88         PrintWriter pw = new PrintWriter(manifestOrig);
  89         pw.println("Manifest-Version: 1.0");
  90         pw.println("Created-By: 1.6.0-internal (Sun Microsystems Inc.)");
  91         pw.println("");
  92         pw.println(animal);
  93         pw.println(specTitle);
  94         pw.close();
  95 
  96         File hello = createTextFile("hello");
  97 
  98         // Create a jar file
  99         final String jarFileName = "um-test.jar";
 100         new File(jarFileName).delete(); // remove pre-existing first!
 101         Main jartool = new Main(out, err, "jar");
 102         boolean status = jartool.run(
 103                                 new String[] {"cfm", jarFileName,
 104                                     manifestOrig.getPath(), hello.getPath() });
 105         check(status);
 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.5.0-special (Sun Microsystems Inc.)";
 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         jartool = new Main(out, err, "jar");
 123         status = jartool.run(
 124             new String[] { "ufm", jarFileName, manifestUpdate.getPath() });
 125         check(status);
 126 
 127         // Extract jar, and verify contents of manifest file
 128         File f = new File(jarFileName);
 129         if (!debug) f.deleteOnExit();
 130         ZipFile zf = new ZipFile(f);
 131         ZipEntry ze = zf.getEntry("META-INF/MANIFEST.MF");
 132         BufferedReader r = new BufferedReader(
 133             new InputStreamReader(zf.getInputStream(ze)));
 134         r.readLine(); // skip Manifest-Version
 135         check(r.readLine().equals(createdBy));
 136         r.readLine(); // skip blank line
 137         check(r.readLine().equals(animal));
 138         String s = r.readLine();
 139         if (s.equals(specVersion)) {
 140             check(r.readLine().equals(specTitle));
 141         } else if (s.equals(specTitle)) {
 142             check(r.readLine().equals(specVersion));
 143         } else {
 144             fail("did not match specVersion nor specTitle");
 145         }
 146         zf.close();
 147     }
 148 
 149     // --------------------- Convenience ---------------------------
 150 
 151     static File createTextFile(String name) throws Throwable {
 152         // Create a text file to put in a jar file
 153         File rc = File.createTempFile(name, ".txt");
 154         if (!debug) rc.deleteOnExit();
 155         PrintWriter pw = new PrintWriter(rc);
 156         pw.println("hello, world");
 157         pw.close();
 158         return rc;
 159     }
 160 
 161     static void checkManifest(String jarFileName, String mainClass)
 162                 throws Throwable {
 163         File f = new File(jarFileName);
 164         if (!debug) f.deleteOnExit();
 165         ZipFile zf = new ZipFile(f);
 166         ZipEntry ze = zf.getEntry("META-INF/MANIFEST.MF");
 167         BufferedReader r = new BufferedReader(
 168             new InputStreamReader(zf.getInputStream(ze)));
 169         String line = r.readLine();
 170         while (line != null && !(line.startsWith("Main-Class:"))) {
 171             line = r.readLine();
 172         }
 173         if (line == null) {
 174             fail("Didn't find Main-Class in manifest");
 175         } else {
 176             check(line.equals("Main-Class: " + mainClass));
 177         }
 178         zf.close();
 179     }
 180 
 181     // --------------------- Infrastructure ---------------------------
 182 
 183     static volatile int passed = 0, failed = 0;
 184 
 185     static void pass() {
 186         passed++;
 187     }
 188 
 189     static void fail() {
 190         failed++;
 191         Thread.dumpStack();
 192     }
 193 
 194     static void fail(String msg) {
 195         System.out.println(msg);
 196         fail();
 197     }
 198 
 199     static void unexpected(Throwable t) {
 200         failed++;
 201         t.printStackTrace();
 202     }
 203 
 204     static void check(boolean cond) {
 205         if (cond)
 206             pass();
 207         else
 208             fail();
 209     }
 210 
 211     static void equal(Object x, Object y) {
 212         if ((x == null) ? (y == null) : x.equals(y))
 213             pass();
 214         else
 215             fail(x + " not equal to " + y);
 216     }
 217 
 218     public static void main(String[] args) throws Throwable {
 219         try {
 220             realMain(args);
 221         } catch (Throwable t) {
 222             unexpected(t);
 223         }
 224         System.out.println("\nPassed = " + passed + " failed = " + failed);
 225         if (failed > 0)
 226             throw new AssertionError("Some tests failed");
 227     }
 228 }