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