1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with this 4 * work for additional information regarding copyright ownership. The ASF 5 * licenses this file to You under the Apache License, Version 2.0 (the 6 * "License"); you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 * License for the specific language governing permissions and limitations under 15 * the License. 16 */ 17 18package org.apache.harmony.archive.tests.java.util.jar; 19 20import dalvik.annotation.KnownFailure; 21import dalvik.annotation.TestLevel; 22import dalvik.annotation.TestTargetClass; 23import dalvik.annotation.TestTargetNew; 24import static tests.support.Support_Exec.execAndGetOutput; 25import static tests.support.Support_Exec.javaProcessBuilder; 26import tests.support.resource.Support_Resources; 27 28import java.io.File; 29import java.io.FileInputStream; 30import java.io.FileOutputStream; 31import java.io.IOException; 32import java.util.jar.Attributes; 33import java.util.jar.JarEntry; 34import java.util.jar.JarOutputStream; 35import java.util.jar.Manifest; 36 37/** 38 * 39 * tests for various cases of java -jar ... execution 40 * 41 */ 42 43@TestTargetClass(JarOutputStream.class) 44public class JarExecTest extends junit.framework.TestCase { 45 /** 46 * regression test for HARMONY-1562 issue 47 * 48 */ 49 @TestTargetNew( 50 level = TestLevel.ADDITIONAL, 51 notes = "Regression functional test. Exception checking missed.", 52 method = "putNextEntry", 53 args = {java.util.zip.ZipEntry.class} 54 ) 55 @KnownFailure("Maybe not a failure, but dalvikvm -jar is not supported (, as yet).") 56 public void test_1562() throws Exception { 57 // create the manifest 58 Manifest man = new Manifest(); 59 Attributes att = man.getMainAttributes(); 60 att.put(Attributes.Name.MANIFEST_VERSION, "1.0"); 61 att.put(Attributes.Name.MAIN_CLASS, "foo.bar.execjartest.Foo"); 62 63 File outputJar = File.createTempFile("hyts_", ".jar"); 64 outputJar.deleteOnExit(); 65 JarOutputStream jout = new JarOutputStream(new FileOutputStream( 66 outputJar), man); 67 File resources = Support_Resources.createTempFolder(); 68 69 for (String jarClass : new String[] {"Foo", "Bar"}) { 70 jout.putNextEntry(new JarEntry("foo/bar/execjartest/" + jarClass 71 + ".class")); 72 jout.write(getResource(resources, "hyts_" + jarClass + ".ser")); 73 } 74 75 jout.close(); 76 77 // execute the JAR and read the result 78 ProcessBuilder builder = javaProcessBuilder(); 79 builder.command().add("-jar"); 80 builder.command().add(outputJar.getAbsolutePath()); 81 assertTrue("Error executing JAR", 82 execAndGetOutput(builder).startsWith("FOOBAR")); 83 } 84 85 /** 86 * tests Class-Path entry in manifest 87 * 88 * @throws Exception in case of troubles 89 */ 90 @TestTargetNew( 91 level = TestLevel.ADDITIONAL, 92 notes = "Functional test.", 93 method = "JarOutputStream", 94 args = {java.io.OutputStream.class, java.util.jar.Manifest.class} 95 ) 96 @KnownFailure("Maybe not a failure, but dalvikvm -jar is not supported (, as yet).") 97 public void test_jar_class_path() throws Exception { 98 File fooJar = File.createTempFile("hyts_", ".jar"); 99 File barJar = File.createTempFile("hyts_", ".jar"); 100 fooJar.deleteOnExit(); 101 barJar.deleteOnExit(); 102 103 // create the manifest 104 Manifest man = new Manifest(); 105 Attributes att = man.getMainAttributes(); 106 att.put(Attributes.Name.MANIFEST_VERSION, "1.0"); 107 att.put(Attributes.Name.MAIN_CLASS, "foo.bar.execjartest.Foo"); 108 att.put(Attributes.Name.CLASS_PATH, barJar.getName()); 109 110 File resources = Support_Resources.createTempFolder(); 111 112 JarOutputStream joutFoo = new JarOutputStream(new FileOutputStream( 113 fooJar), man); 114 joutFoo.putNextEntry(new JarEntry("foo/bar/execjartest/Foo.class")); 115 joutFoo.write(getResource(resources, "hyts_Foo.ser")); 116 joutFoo.close(); 117 118 JarOutputStream joutBar = new JarOutputStream(new FileOutputStream( 119 barJar)); 120 joutBar.putNextEntry(new JarEntry("foo/bar/execjartest/Bar.class")); 121 joutBar.write(getResource(resources, "hyts_Bar.ser")); 122 joutBar.close(); 123 124 // execute the JAR and read the result 125 ProcessBuilder builder = javaProcessBuilder(); 126 builder.command().add("-jar"); 127 builder.command().add(fooJar.getAbsolutePath()); 128 assertTrue("Error executing JAR", 129 execAndGetOutput(builder).startsWith("FOOBAR")); 130 131 // rewrite manifest so it contains not only reference to bar but useless 132 // entries as well 133 att.put(Attributes.Name.CLASS_PATH, "xx yy zz " + barJar.getName()); 134 joutFoo = new JarOutputStream(new FileOutputStream(fooJar), man); 135 joutFoo.putNextEntry(new JarEntry("foo/bar/execjartest/Foo.class")); 136 joutFoo.write(getResource(resources, "hyts_Foo.ser")); 137 joutFoo.close(); 138 // execute the JAR and read the result 139 assertTrue("Error executing JAR", 140 execAndGetOutput(builder).startsWith( "FOOBAR")); 141 142 // play with relative file names - put relative path as ../<parent dir 143 // name>/xx.jar 144 att.put(Attributes.Name.CLASS_PATH, ".." + File.separator 145 + barJar.getParentFile().getName() + File.separator 146 + barJar.getName()); 147 joutFoo = new JarOutputStream(new FileOutputStream(fooJar), man); 148 joutFoo.putNextEntry(new JarEntry("foo/bar/execjartest/Foo.class")); 149 joutFoo.write(getResource(resources, "hyts_Foo.ser")); 150 joutFoo.close(); 151 // execute the JAR and read the result 152 assertTrue("Error executing JAR", 153 execAndGetOutput(builder).startsWith( "FOOBAR")); 154 } 155 156 /** 157 * tests case when Main-Class is not in the jar launched but in another jar 158 * referenced by Class-Path 159 * 160 * @throws Exception in case of troubles 161 */ 162 @TestTargetNew( 163 level = TestLevel.ADDITIONAL, 164 notes = "Functional test.", 165 method = "JarOutputStream", 166 args = {java.io.OutputStream.class, java.util.jar.Manifest.class} 167 ) 168 @KnownFailure("Maybe not a failure, but dalvikvm -jar is not supported (, as yet).") 169 public void test_main_class_in_another_jar() throws Exception { 170 File fooJar = File.createTempFile("hyts_", ".jar"); 171 File barJar = File.createTempFile("hyts_", ".jar"); 172 fooJar.deleteOnExit(); 173 barJar.deleteOnExit(); 174 175 // create the manifest 176 Manifest man = new Manifest(); 177 Attributes att = man.getMainAttributes(); 178 att.put(Attributes.Name.MANIFEST_VERSION, "1.0"); 179 att.put(Attributes.Name.MAIN_CLASS, "foo.bar.execjartest.Foo"); 180 att.put(Attributes.Name.CLASS_PATH, fooJar.getName()); 181 182 File resources = Support_Resources.createTempFolder(); 183 184 JarOutputStream joutFoo = new JarOutputStream(new FileOutputStream( 185 fooJar)); 186 joutFoo.putNextEntry(new JarEntry("foo/bar/execjartest/Foo.class")); 187 joutFoo.write(getResource(resources, "hyts_Foo.ser")); 188 joutFoo.close(); 189 190 JarOutputStream joutBar = new JarOutputStream(new FileOutputStream( 191 barJar), man); 192 joutBar.putNextEntry(new JarEntry("foo/bar/execjartest/Bar.class")); 193 joutBar.write(getResource(resources, "hyts_Bar.ser")); 194 joutBar.close(); 195 196 // execute the JAR and read the result 197 ProcessBuilder builder = javaProcessBuilder(); 198 builder.command().add("-jar"); 199 builder.command().add(barJar.getAbsolutePath()); 200 assertTrue("Error executing JAR", 201 execAndGetOutput(builder).startsWith("FOOBAR")); 202 } 203 204 @TestTargetNew( 205 level = TestLevel.ADDITIONAL, 206 notes = "Functional test.", 207 method = "JarOutputStream", 208 args = {java.io.OutputStream.class, java.util.jar.Manifest.class} 209 ) 210 @KnownFailure("Maybe not a failure, but dalvikvm -jar is not supported (, as yet).") 211 public void test_classpath() throws Exception { 212 File resources = Support_Resources.createTempFolder(); 213 214 File fooJar = File.createTempFile("hyts_", ".jar"); 215 fooJar.deleteOnExit(); 216 217 JarOutputStream joutFoo = new JarOutputStream(new FileOutputStream( 218 fooJar)); 219 joutFoo.putNextEntry(new JarEntry("foo/bar/execjartest/Foo.class")); 220 joutFoo.write(getResource(resources, "hyts_Foo.ser")); 221 joutFoo.putNextEntry(new JarEntry("foo/bar/execjartest/Bar.class")); 222 joutFoo.write(getResource(resources, "hyts_Bar.ser")); 223 joutFoo.close(); 224 225 // execute the JAR and read the result 226 ProcessBuilder builder = javaProcessBuilder(); 227 builder.environment().put("CLASSPATH", fooJar.getAbsolutePath()); 228 builder.command().add("foo.bar.execjartest.Foo"); 229 230 assertTrue("Error executing class from ClassPath", 231 execAndGetOutput(builder).startsWith("FOOBAR")); 232 233 // ok - next try - add -cp to path - it should override env 234 File booJar = File.createTempFile("hyts_", ".jar"); 235 booJar.deleteOnExit(); 236 237 JarOutputStream joutBoo = new JarOutputStream(new FileOutputStream( 238 booJar)); 239 joutBoo.putNextEntry(new JarEntry("foo/bar/execjartest/Foo.class")); 240 String booBody = new String(getResource(resources, "hyts_Foo.ser"), 241 "iso-8859-1"); 242 booBody = booBody.replaceFirst("FOO", "BOO"); 243 joutBoo.write(booBody.getBytes("iso-8859-1")); 244 joutBoo.putNextEntry(new JarEntry("foo/bar/execjartest/Bar.class")); 245 String farBody = new String(getResource(resources, "hyts_Bar.ser"), 246 "iso-8859-1"); 247 farBody = farBody.replaceFirst("BAR", "FAR"); 248 joutBoo.write(farBody.getBytes("iso-8859-1")); 249 joutBoo.close(); 250 251 builder = javaProcessBuilder(); 252 builder.environment().put("CLASSPATH", fooJar.getAbsolutePath()); 253 builder.command().add("-cp"); 254 builder.command().add(booJar.getAbsolutePath()); 255 builder.command().add("foo.bar.execjartest.Foo"); 256 257 assertTrue("Error executing class specified by -cp", 258 execAndGetOutput(builder).startsWith("BOOFAR")); 259 260 // now add -jar option - it should override env and classpath 261 Manifest man = new Manifest(); 262 Attributes att = man.getMainAttributes(); 263 att.put(Attributes.Name.MANIFEST_VERSION, "1.0"); 264 att.put(Attributes.Name.MAIN_CLASS, "foo.bar.execjartest.Foo"); 265 266 File zooJar = File.createTempFile("hyts_", ".jar"); 267 zooJar.deleteOnExit(); 268 269 JarOutputStream joutZoo = new JarOutputStream(new FileOutputStream( 270 zooJar), man); 271 joutZoo.putNextEntry(new JarEntry("foo/bar/execjartest/Foo.class")); 272 String zooBody = new String(getResource(resources, "hyts_Foo.ser"), 273 "iso-8859-1"); 274 zooBody = zooBody.replaceFirst("FOO", "ZOO"); 275 joutZoo.write(zooBody.getBytes("iso-8859-1")); 276 joutZoo.putNextEntry(new JarEntry("foo/bar/execjartest/Bar.class")); 277 String zarBody = new String(getResource(resources, "hyts_Bar.ser"), 278 "iso-8859-1"); 279 zarBody = zarBody.replaceFirst("BAR", "ZAR"); 280 joutZoo.write(zarBody.getBytes("iso-8859-1")); 281 joutZoo.close(); 282 283 builder = javaProcessBuilder(); 284 builder.environment().put("CLASSPATH", fooJar.getAbsolutePath()); 285 builder.command().add("-cp"); 286 builder.command().add(booJar.getAbsolutePath()); 287 builder.command().add("-jar"); 288 builder.command().add(zooJar.getAbsolutePath()); 289 290 assertTrue("Error executing class specified by -jar", 291 execAndGetOutput(builder).startsWith("ZOOZAR")); 292 } 293 294 private static byte[] getResource(File tempDir, String resourceName) 295 throws IOException { 296 Support_Resources.copyFile(tempDir, null, resourceName); 297 File resourceFile = new File(tempDir, resourceName); 298 resourceFile.deleteOnExit(); 299 300 // read whole resource data into memory 301 byte[] resourceBody = new byte[(int) resourceFile.length()]; 302 FileInputStream fis = new FileInputStream(resourceFile); 303 fis.read(resourceBody); 304 fis.close(); 305 306 return resourceBody; 307 } 308 309} 310