Home | History | Annotate | Download | only in jar
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  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,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 package org.apache.harmony.archive.tests.java.util.jar;
     18 
     19 
     20 import junit.framework.TestCase;
     21 
     22 import tests.support.Support_PlatformFile;
     23 import tests.support.resource.Support_Resources;
     24 
     25 import java.io.ByteArrayOutputStream;
     26 import java.io.File;
     27 import java.io.FileOutputStream;
     28 import java.io.IOException;
     29 import java.io.InputStream;
     30 import java.net.URL;
     31 import java.security.Permission;
     32 import java.security.cert.Certificate;
     33 import java.util.Enumeration;
     34 import java.util.Vector;
     35 import java.util.jar.Attributes;
     36 import java.util.jar.JarEntry;
     37 import java.util.jar.JarFile;
     38 import java.util.jar.JarOutputStream;
     39 import java.util.jar.Manifest;
     40 import java.util.zip.ZipEntry;
     41 import java.util.zip.ZipException;
     42 import java.util.zip.ZipFile;
     43 
     44 
     45 public class JarFileTest extends TestCase {
     46 
     47     // BEGIN android-added
     48     public byte[] getAllBytesFromStream(InputStream is) throws IOException {
     49         ByteArrayOutputStream bs = new ByteArrayOutputStream();
     50         byte[] buf = new byte[666];
     51         int iRead;
     52         int off;
     53         while (is.available() > 0) {
     54             iRead = is.read(buf, 0, buf.length);
     55             if (iRead > 0) bs.write(buf, 0, iRead);
     56         }
     57         return bs.toByteArray();
     58     }
     59 
     60     // END android-added
     61 
     62     private final String jarName = "hyts_patch.jar"; // a 'normal' jar file
     63 
     64     private final String jarName2 = "hyts_patch2.jar";
     65 
     66     private final String jarName3 = "hyts_manifest1.jar";
     67 
     68     private final String jarName4 = "hyts_signed.jar";
     69 
     70     private final String jarName5 = "hyts_signed_inc.jar";
     71 
     72     private final String jarName6 = "hyts_signed_sha256withrsa.jar";
     73 
     74     private final String jarName7 = "hyts_signed_sha256digest_sha256withrsa.jar";
     75 
     76     private final String jarName8 = "hyts_signed_sha512digest_sha512withecdsa.jar";
     77 
     78     private final String authAttrsJar = "hyts_signed_authAttrs.jar";
     79 
     80     private final String entryName = "foo/bar/A.class";
     81 
     82     private final String entryName3 = "coucou/FileAccess.class";
     83 
     84     private final String integrateJar = "Integrate.jar";
     85 
     86     private final String integrateJarEntry = "Test.class";
     87 
     88     private final String emptyEntryJar = "EmptyEntries_signed.jar";
     89 
     90     private final String emptyEntry1 = "subfolder/internalSubset01.js";
     91 
     92     private final String emptyEntry2 = "svgtest.js";
     93 
     94     private final String emptyEntry3 = "svgunit.js";
     95 
     96     private File resources;
     97 
     98     // custom security manager
     99     SecurityManager sm = new SecurityManager() {
    100         final String forbidenPermissionName = "user.dir";
    101 
    102         public void checkPermission(Permission perm) {
    103             if (perm.getName().equals(forbidenPermissionName)) {
    104                 throw new SecurityException();
    105             }
    106         }
    107     };
    108 
    109     @Override
    110     protected void setUp() {
    111         resources = Support_Resources.createTempFolder();
    112     }
    113 
    114     /**
    115      * java.util.jar.JarFile#JarFile(java.io.File)
    116      */
    117     public void test_ConstructorLjava_io_File() {
    118         try {
    119             JarFile jarFile = new JarFile(new File("Wrong.file"));
    120             fail("Should throw IOException");
    121         } catch (IOException e) {
    122             // expected
    123         }
    124 
    125         try {
    126             Support_Resources.copyFile(resources, null, jarName);
    127             JarFile jarFile = new JarFile(new File(resources, jarName));
    128         } catch (IOException e) {
    129             fail("Should not throw IOException");
    130         }
    131     }
    132 
    133     /**
    134      * java.util.jar.JarFile#JarFile(java.lang.String)
    135      */
    136     public void test_ConstructorLjava_lang_String() {
    137         try {
    138             JarFile jarFile = new JarFile("Wrong.file");
    139             fail("Should throw IOException");
    140         } catch (IOException e) {
    141             // expected
    142         }
    143 
    144         try {
    145             Support_Resources.copyFile(resources, null, jarName);
    146             String fileName = (new File(resources, jarName)).getCanonicalPath();
    147             JarFile jarFile = new JarFile(fileName);
    148         } catch (IOException e) {
    149             fail("Should not throw IOException");
    150         }
    151     }
    152 
    153     /**
    154      * java.util.jar.JarFile#JarFile(java.lang.String, boolean)
    155      */
    156     public void test_ConstructorLjava_lang_StringZ() {
    157         try {
    158             JarFile jarFile = new JarFile("Wrong.file", false);
    159             fail("Should throw IOException");
    160         } catch (IOException e) {
    161             // expected
    162         }
    163 
    164         try {
    165             Support_Resources.copyFile(resources, null, jarName);
    166             String fileName = (new File(resources, jarName)).getCanonicalPath();
    167             JarFile jarFile = new JarFile(fileName, true);
    168         } catch (IOException e) {
    169             fail("Should not throw IOException");
    170         }
    171     }
    172 
    173     /**
    174      * java.util.jar.JarFile#JarFile(java.io.File, boolean)
    175      */
    176     public void test_ConstructorLjava_io_FileZ() {
    177         try {
    178             JarFile jarFile = new JarFile(new File("Wrong.file"), true);
    179             fail("Should throw IOException");
    180         } catch (IOException e) {
    181             // expected
    182         }
    183 
    184         try {
    185             Support_Resources.copyFile(resources, null, jarName);
    186             JarFile jarFile = new JarFile(new File(resources, jarName), false);
    187         } catch (IOException e) {
    188             fail("Should not throw IOException");
    189         }
    190     }
    191 
    192     /**
    193      * java.util.jar.JarFile#JarFile(java.io.File, boolean, int)
    194      */
    195     public void test_ConstructorLjava_io_FileZI() {
    196         try {
    197             JarFile jarFile = new JarFile(new File("Wrong.file"), true,
    198                     ZipFile.OPEN_READ);
    199             fail("Should throw IOException");
    200         } catch (IOException e) {
    201             // expected
    202         }
    203 
    204         try {
    205             Support_Resources.copyFile(resources, null, jarName);
    206             JarFile jarFile = new JarFile(new File(resources, jarName), false,
    207                     ZipFile.OPEN_READ);
    208         } catch (IOException e) {
    209             fail("Should not throw IOException");
    210         }
    211 
    212         try {
    213             Support_Resources.copyFile(resources, null, jarName);
    214             JarFile jarFile = new JarFile(new File(resources, jarName), false,
    215                     ZipFile.OPEN_READ | ZipFile.OPEN_DELETE + 33);
    216             fail("Should throw IllegalArgumentException");
    217         } catch (IOException e) {
    218             fail("Should not throw IOException");
    219         } catch (IllegalArgumentException e) {
    220             // expected
    221         }
    222     }
    223 
    224     /**
    225      * Constructs JarFile object.
    226      *
    227      * java.util.jar.JarFile#JarFile(java.io.File)
    228      * java.util.jar.JarFile#JarFile(java.lang.String)
    229      */
    230     public void testConstructor_file() throws IOException {
    231         File f = new File(resources, jarName);
    232         Support_Resources.copyFile(resources, null, jarName);
    233         assertTrue(new JarFile(f).getEntry(entryName).getName().equals(
    234                 entryName));
    235         assertTrue(new JarFile(f.getPath()).getEntry(entryName).getName()
    236                 .equals(entryName));
    237     }
    238 
    239     /**
    240      * java.util.jar.JarFile#entries()
    241      */
    242     public void test_entries() throws Exception {
    243         /*
    244          * Note only (and all of) the following should be contained in the file
    245          * META-INF/ META-INF/MANIFEST.MF foo/ foo/bar/ foo/bar/A.class Blah.txt
    246          */
    247         Support_Resources.copyFile(resources, null, jarName);
    248         JarFile jarFile = new JarFile(new File(resources, jarName));
    249         Enumeration<JarEntry> e = jarFile.entries();
    250         int i;
    251         for (i = 0; e.hasMoreElements(); i++) {
    252             e.nextElement();
    253         }
    254         assertEquals(jarFile.size(), i);
    255         jarFile.close();
    256         assertEquals(6, i);
    257     }
    258 
    259     public void test_entries2() throws Exception {
    260         Support_Resources.copyFile(resources, null, jarName);
    261         JarFile jarFile = new JarFile(new File(resources, jarName));
    262         Enumeration<JarEntry> enumeration = jarFile.entries();
    263         jarFile.close();
    264         try {
    265             enumeration.hasMoreElements();
    266             fail("hasMoreElements() did not detect a closed jar file");
    267         } catch (IllegalStateException e) {
    268         }
    269         Support_Resources.copyFile(resources, null, jarName);
    270         jarFile = new JarFile(new File(resources, jarName));
    271         enumeration = jarFile.entries();
    272         jarFile.close();
    273         try {
    274             enumeration.nextElement();
    275             fail("nextElement() did not detect closed jar file");
    276         } catch (IllegalStateException e) {
    277         }
    278     }
    279 
    280     /**
    281      * @throws IOException
    282      * java.util.jar.JarFile#getJarEntry(java.lang.String)
    283      */
    284     public void test_getEntryLjava_lang_String() throws IOException {
    285         try {
    286             Support_Resources.copyFile(resources, null, jarName);
    287             JarFile jarFile = new JarFile(new File(resources, jarName));
    288             assertEquals("Error in returned entry", 311, jarFile.getEntry(
    289                     entryName).getSize());
    290             jarFile.close();
    291         } catch (Exception e) {
    292             fail("Exception during test: " + e.toString());
    293         }
    294 
    295         Support_Resources.copyFile(resources, null, jarName);
    296         JarFile jarFile = new JarFile(new File(resources, jarName));
    297         Enumeration<JarEntry> enumeration = jarFile.entries();
    298         assertTrue(enumeration.hasMoreElements());
    299         while (enumeration.hasMoreElements()) {
    300             JarEntry je = enumeration.nextElement();
    301             jarFile.getEntry(je.getName());
    302         }
    303 
    304         enumeration = jarFile.entries();
    305         assertTrue(enumeration.hasMoreElements());
    306         JarEntry je = enumeration.nextElement();
    307         try {
    308             jarFile.close();
    309             jarFile.getEntry(je.getName());
    310             // fail("IllegalStateException expected.");
    311         } catch (IllegalStateException ee) { // Per documentation exception
    312             // may be thrown.
    313             // expected
    314         }
    315     }
    316 
    317     /**
    318      * @throws IOException
    319      * java.util.jar.JarFile#getJarEntry(java.lang.String)
    320      */
    321     public void test_getJarEntryLjava_lang_String() throws IOException {
    322         try {
    323             Support_Resources.copyFile(resources, null, jarName);
    324             JarFile jarFile = new JarFile(new File(resources, jarName));
    325             assertEquals("Error in returned entry", 311, jarFile.getJarEntry(
    326                     entryName).getSize());
    327             jarFile.close();
    328         } catch (Exception e) {
    329             fail("Exception during test: " + e.toString());
    330         }
    331 
    332         Support_Resources.copyFile(resources, null, jarName);
    333         JarFile jarFile = new JarFile(new File(resources, jarName));
    334         Enumeration<JarEntry> enumeration = jarFile.entries();
    335         assertTrue(enumeration.hasMoreElements());
    336         while (enumeration.hasMoreElements()) {
    337             JarEntry je = enumeration.nextElement();
    338             jarFile.getJarEntry(je.getName());
    339         }
    340 
    341         enumeration = jarFile.entries();
    342         assertTrue(enumeration.hasMoreElements());
    343         JarEntry je = enumeration.nextElement();
    344         try {
    345             jarFile.close();
    346             jarFile.getJarEntry(je.getName());
    347             // fail("IllegalStateException expected.");
    348         } catch (IllegalStateException ee) { // Per documentation exception
    349             // may be thrown.
    350             // expected
    351         }
    352     }
    353 
    354 
    355     /**
    356      * java.util.jar.JarFile#getJarEntry(java.lang.String)
    357      */
    358     public void testGetJarEntry() throws Exception {
    359         Support_Resources.copyFile(resources, null, jarName);
    360         JarFile jarFile = new JarFile(new File(resources, jarName));
    361         assertEquals("Error in returned entry", 311, jarFile.getEntry(
    362                 entryName).getSize());
    363         jarFile.close();
    364 
    365         // tests for signed jars
    366         // test all signed jars in the /Testres/Internal/SignedJars directory
    367         String jarDirUrl = Support_Resources
    368                 .getResourceURL("/../internalres/signedjars");
    369         Vector<String> signedJars = new Vector<String>();
    370         try {
    371             InputStream is = new URL(jarDirUrl + "/jarlist.txt").openStream();
    372             while (is.available() > 0) {
    373                 StringBuilder linebuff = new StringBuilder(80); // Typical line
    374                 // length
    375                 done: while (true) {
    376                     int nextByte = is.read();
    377                     switch (nextByte) {
    378                         case -1:
    379                             break done;
    380                         case (byte) '\r':
    381                             if (linebuff.length() == 0) {
    382                                 // ignore
    383                             }
    384                             break done;
    385                         case (byte) '\n':
    386                             if (linebuff.length() == 0) {
    387                                 // ignore
    388                             }
    389                             break done;
    390                         default:
    391                             linebuff.append((char) nextByte);
    392                     }
    393                 }
    394                 if (linebuff.length() == 0) {
    395                     break;
    396                 }
    397                 String line = linebuff.toString();
    398                 signedJars.add(line);
    399             }
    400             is.close();
    401         } catch (IOException e) {
    402             // no list of jars found
    403         }
    404 
    405         for (int i = 0; i < signedJars.size(); i++) {
    406             String jarName = signedJars.get(i);
    407             try {
    408                 File file = Support_Resources.getExternalLocalFile(jarDirUrl
    409                         + "/" + jarName);
    410                 jarFile = new JarFile(file, true);
    411                 boolean foundCerts = false;
    412                 Enumeration<JarEntry> e = jarFile.entries();
    413                 while (e.hasMoreElements()) {
    414                     JarEntry entry = e.nextElement();
    415                     InputStream is = jarFile.getInputStream(entry);
    416                     is.skip(100000);
    417                     is.close();
    418                     Certificate[] certs = entry.getCertificates();
    419                     if (certs != null && certs.length > 0) {
    420                         foundCerts = true;
    421                         break;
    422                     }
    423                 }
    424                 assertTrue(
    425                         "No certificates found during signed jar test for jar \""
    426                                 + jarName + "\"", foundCerts);
    427             } catch (IOException e) {
    428                 fail("Exception during signed jar test for jar \"" + jarName
    429                         + "\": " + e.toString());
    430             }
    431         }
    432     }
    433 
    434     /**
    435      * java.util.jar.JarFile#getManifest()
    436      */
    437     public void test_getManifest() {
    438         // Test for method java.util.jar.Manifest
    439         // java.util.jar.JarFile.getManifest()
    440         try {
    441             Support_Resources.copyFile(resources, null, jarName);
    442             JarFile jarFile = new JarFile(new File(resources, jarName));
    443             assertNotNull("Error--Manifest not returned", jarFile.getManifest());
    444             jarFile.close();
    445         } catch (Exception e) {
    446             fail("Exception during 1st test: " + e.toString());
    447         }
    448         try {
    449             Support_Resources.copyFile(resources, null, jarName2);
    450             JarFile jarFile = new JarFile(new File(resources, jarName2));
    451             assertNull("Error--should have returned null", jarFile
    452                     .getManifest());
    453             jarFile.close();
    454         } catch (Exception e) {
    455             fail("Exception during 2nd test: " + e.toString());
    456         }
    457 
    458         try {
    459             // jarName3 was created using the following test
    460             Support_Resources.copyFile(resources, null, jarName3);
    461             JarFile jarFile = new JarFile(new File(resources, jarName3));
    462             assertNotNull("Should find manifest without verifying", jarFile
    463                     .getManifest());
    464             jarFile.close();
    465         } catch (Exception e) {
    466             fail("Exception during 3rd test: " + e.toString());
    467         }
    468 
    469         try {
    470             // this is used to create jarName3 used in the previous test
    471             Manifest manifest = new Manifest();
    472             Attributes attributes = manifest.getMainAttributes();
    473             attributes.put(new Attributes.Name("Manifest-Version"), "1.0");
    474             ByteArrayOutputStream manOut = new ByteArrayOutputStream();
    475             manifest.write(manOut);
    476             byte[] manBytes = manOut.toByteArray();
    477             File file = File.createTempFile(
    478                     Support_PlatformFile.getNewPlatformFile("hyts_manifest1",
    479                             ""), ".jar");
    480             JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(
    481                     file.getAbsolutePath()));
    482             ZipEntry entry = new ZipEntry("META-INF/");
    483             entry.setSize(0);
    484             jarOut.putNextEntry(entry);
    485             entry = new ZipEntry(JarFile.MANIFEST_NAME);
    486             entry.setSize(manBytes.length);
    487             jarOut.putNextEntry(entry);
    488             jarOut.write(manBytes);
    489             entry = new ZipEntry("myfile");
    490             entry.setSize(1);
    491             jarOut.putNextEntry(entry);
    492             jarOut.write(65);
    493             jarOut.close();
    494             JarFile jar = new JarFile(file.getAbsolutePath(), false);
    495             assertNotNull("Should find manifest without verifying", jar
    496                     .getManifest());
    497             jar.close();
    498             file.delete();
    499         } catch (IOException e) {
    500             fail("IOException 3");
    501         }
    502         try {
    503             Support_Resources.copyFile(resources, null, jarName2);
    504             JarFile jF = new JarFile(new File(resources, jarName2));
    505             jF.close();
    506             jF.getManifest();
    507             fail("FAILED: expected IllegalStateException");
    508         } catch (IllegalStateException ise) {
    509             // expected;
    510         } catch (Exception e) {
    511             fail("Exception during 4th test: " + e.toString());
    512         }
    513 
    514         Support_Resources.copyFile(resources, null, "Broken_manifest.jar");
    515         JarFile jf;
    516         try {
    517             jf = new JarFile(new File(resources, "Broken_manifest.jar"));
    518             jf.getManifest();
    519             fail("IOException expected.");
    520         } catch (IOException e) {
    521             // expected.
    522         }
    523     }
    524 
    525     /**
    526      * java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)
    527      */
    528     // This test doesn't pass on RI. If entry size is set up incorrectly,
    529     // SecurityException is thrown. But SecurityException is thrown on RI only
    530     // if jar file is signed incorrectly.
    531     public void test_getInputStreamLjava_util_jar_JarEntry_subtest0() throws Exception {
    532         File signedFile = null;
    533         try {
    534             Support_Resources.copyFile(resources, null, jarName4);
    535             signedFile = new File(resources, jarName4);
    536         } catch (Exception e) {
    537             fail("Failed to create local file 2: " + e);
    538         }
    539 
    540         try {
    541             JarFile jar = new JarFile(signedFile);
    542             JarEntry entry = new JarEntry(entryName3);
    543             InputStream in = jar.getInputStream(entry);
    544             in.read();
    545         } catch (Exception e) {
    546             fail("Exception during test 3: " + e);
    547         }
    548 
    549         try {
    550             JarFile jar = new JarFile(signedFile);
    551             JarEntry entry = new JarEntry(entryName3);
    552             InputStream in = jar.getInputStream(entry);
    553             // BEGIN android-added
    554             byte[] dummy = getAllBytesFromStream(in);
    555             // END android-added
    556             assertNull("found certificates", entry.getCertificates());
    557         } catch (Exception e) {
    558             fail("Exception during test 4: " + e);
    559         }
    560 
    561         try {
    562             JarFile jar = new JarFile(signedFile);
    563             JarEntry entry = new JarEntry(entryName3);
    564             entry.setSize(1076);
    565             InputStream in = jar.getInputStream(entry);
    566             // BEGIN android-added
    567             byte[] dummy = getAllBytesFromStream(in);
    568             // END android-added
    569             fail("SecurityException should be thrown.");
    570         } catch (SecurityException e) {
    571             // expected
    572         } catch (Exception e) {
    573             fail("Exception during test 5: " + e);
    574         }
    575 
    576         try {
    577             Support_Resources.copyFile(resources, null, jarName5);
    578             signedFile = new File(resources, jarName5);
    579         } catch (Exception e) {
    580             fail("Failed to create local file 5: " + e);
    581         }
    582 
    583         try {
    584             JarFile jar = new JarFile(signedFile);
    585             JarEntry entry = new JarEntry(entryName3);
    586             InputStream in = jar.getInputStream(entry);
    587             fail("SecurityException should be thrown.");
    588         } catch (SecurityException e) {
    589             // expected
    590         } catch (Exception e) {
    591             fail("Exception during test 5: " + e);
    592         }
    593 
    594         // SHA1 digest, SHA256withRSA signed JAR
    595         checkSignedJar(jarName6);
    596 
    597         // SHA-256 digest, SHA256withRSA signed JAR
    598         checkSignedJar(jarName7);
    599 
    600         // SHA-512 digest, SHA512withECDSA signed JAR
    601         checkSignedJar(jarName8);
    602 
    603         // JAR with a signature that has PKCS#7 Authenticated Attributes
    604         checkSignedJar(authAttrsJar);
    605     }
    606 
    607     private void checkSignedJar(String jarName) throws Exception {
    608         Support_Resources.copyFile(resources, null, jarName);
    609 
    610         File file = new File(resources, jarName);
    611 
    612         JarFile jarFile = new JarFile(file, true);
    613 
    614         boolean foundCerts = false;
    615 
    616         Enumeration<JarEntry> e = jarFile.entries();
    617         while (e.hasMoreElements()) {
    618             JarEntry entry = e.nextElement();
    619             InputStream is = jarFile.getInputStream(entry);
    620             is.skip(100000);
    621             is.close();
    622             Certificate[] certs = entry.getCertificates();
    623             if (certs != null && certs.length > 0) {
    624                 foundCerts = true;
    625                 break;
    626             }
    627         }
    628 
    629         assertTrue(
    630                 "No certificates found during signed jar test for jar \""
    631                         + jarName + "\"", foundCerts);
    632     }
    633 
    634     /*
    635      * The jar created by 1.4 which does not provide a
    636      * algorithm-Digest-Manifest-Main-Attributes entry in .SF file.
    637      */
    638     public void test_Jar_created_before_java_5() throws IOException {
    639         String modifiedJarName = "Created_by_1_4.jar";
    640         Support_Resources.copyFile(resources, null, modifiedJarName);
    641         JarFile jarFile = new JarFile(new File(resources, modifiedJarName),
    642                 true);
    643         Enumeration<JarEntry> entries = jarFile.entries();
    644         while (entries.hasMoreElements()) {
    645             ZipEntry zipEntry = entries.nextElement();
    646             jarFile.getInputStream(zipEntry);
    647         }
    648     }
    649 
    650     /* The jar is intact, then everything is all right. */
    651     public void test_JarFile_Integrate_Jar() throws IOException {
    652         String modifiedJarName = "Integrate.jar";
    653         Support_Resources.copyFile(resources, null, modifiedJarName);
    654         JarFile jarFile = new JarFile(new File(resources, modifiedJarName),
    655                 true);
    656         Enumeration<JarEntry> entries = jarFile.entries();
    657         while (entries.hasMoreElements()) {
    658             ZipEntry zipEntry = entries.nextElement();
    659             jarFile.getInputStream(zipEntry).skip(Long.MAX_VALUE);
    660         }
    661     }
    662 
    663     /**
    664      * The jar is intact, but the entry object is modified.
    665      */
    666     public void testJarVerificationModifiedEntry() throws IOException {
    667         Support_Resources.copyFile(resources, null, integrateJar);
    668         File f = new File(resources, integrateJar);
    669 
    670         JarFile jarFile = new JarFile(f);
    671         ZipEntry zipEntry = jarFile.getJarEntry(integrateJarEntry);
    672         zipEntry.setSize(zipEntry.getSize() + 1);
    673         jarFile.getInputStream(zipEntry).skip(Long.MAX_VALUE);
    674 
    675         jarFile = new JarFile(f);
    676         zipEntry = jarFile.getJarEntry(integrateJarEntry);
    677         zipEntry.setSize(zipEntry.getSize() - 1);
    678         try {
    679             //jarFile.getInputStream(zipEntry).skip(Long.MAX_VALUE);
    680             jarFile.getInputStream(zipEntry).read(new byte[5000], 0, 5000);
    681             fail("SecurityException expected");
    682         } catch (SecurityException e) {
    683             // desired
    684         }
    685     }
    686 
    687     /*
    688      * If another entry is inserted into Manifest, no security exception will be
    689      * thrown out.
    690      */
    691     public void test_JarFile_InsertEntry_in_Manifest_Jar() throws IOException {
    692         String modifiedJarName = "Inserted_Entry_Manifest.jar";
    693         Support_Resources.copyFile(resources, null, modifiedJarName);
    694         JarFile jarFile = new JarFile(new File(resources, modifiedJarName),
    695                 true);
    696         Enumeration<JarEntry> entries = jarFile.entries();
    697         int count = 0;
    698         while (entries.hasMoreElements()) {
    699 
    700             ZipEntry zipEntry = entries.nextElement();
    701             jarFile.getInputStream(zipEntry);
    702             count++;
    703         }
    704         assertEquals(5, count);
    705     }
    706 
    707     /*
    708      * If another entry is inserted into Manifest, no security exception will be
    709      * thrown out.
    710      */
    711     public void test_Inserted_Entry_Manifest_with_DigestCode()
    712             throws IOException {
    713         String modifiedJarName = "Inserted_Entry_Manifest_with_DigestCode.jar";
    714         Support_Resources.copyFile(resources, null, modifiedJarName);
    715         JarFile jarFile = new JarFile(new File(resources, modifiedJarName),
    716                 true);
    717         Enumeration<JarEntry> entries = jarFile.entries();
    718         int count = 0;
    719         while (entries.hasMoreElements()) {
    720             ZipEntry zipEntry = entries.nextElement();
    721             jarFile.getInputStream(zipEntry);
    722             count++;
    723         }
    724         assertEquals(5, count);
    725     }
    726 
    727     /*
    728      * The content of Test.class is modified, jarFile.getInputStream will not
    729      * throw security Exception, but it will anytime before the inputStream got
    730      * from getInputStream method has been read to end.
    731      */
    732     public void test_JarFile_Modified_Class() throws IOException {
    733         String modifiedJarName = "Modified_Class.jar";
    734         Support_Resources.copyFile(resources, null, modifiedJarName);
    735         JarFile jarFile = new JarFile(new File(resources, modifiedJarName),
    736                 true);
    737         Enumeration<JarEntry> entries = jarFile.entries();
    738         while (entries.hasMoreElements()) {
    739             ZipEntry zipEntry = entries.nextElement();
    740             jarFile.getInputStream(zipEntry);
    741         }
    742         /* The content of Test.class has been tampered. */
    743         ZipEntry zipEntry = jarFile.getEntry("Test.class");
    744         InputStream in = jarFile.getInputStream(zipEntry);
    745         byte[] buffer = new byte[1024];
    746         try {
    747             while (in.available() > 0) {
    748                 in.read(buffer);
    749             }
    750             fail("SecurityException expected");
    751         } catch (SecurityException e) {
    752             // desired
    753         }
    754     }
    755 
    756     /*
    757      * In the Modified.jar, the main attributes of META-INF/MANIFEST.MF is
    758      * tampered manually. Hence the RI 5.0 JarFile.getInputStream of any
    759      * JarEntry will throw security exception.
    760      */
    761     public void test_JarFile_Modified_Manifest_MainAttributes()
    762             throws IOException {
    763         String modifiedJarName = "Modified_Manifest_MainAttributes.jar";
    764         Support_Resources.copyFile(resources, null, modifiedJarName);
    765         JarFile jarFile = new JarFile(new File(resources, modifiedJarName),
    766                 true);
    767         Enumeration<JarEntry> entries = jarFile.entries();
    768         while (entries.hasMoreElements()) {
    769             ZipEntry zipEntry = entries.nextElement();
    770             try {
    771                 jarFile.getInputStream(zipEntry);
    772                 fail("SecurityException expected");
    773             } catch (SecurityException e) {
    774                 // desired
    775             }
    776         }
    777     }
    778 
    779     /*
    780      * It is all right in our original JarFile. If the Entry Attributes, for
    781      * example Test.class in our jar, the jarFile.getInputStream will throw
    782      * Security Exception.
    783      */
    784     public void test_JarFile_Modified_Manifest_EntryAttributes()
    785             throws IOException {
    786         String modifiedJarName = "Modified_Manifest_EntryAttributes.jar";
    787         Support_Resources.copyFile(resources, null, modifiedJarName);
    788         JarFile jarFile = new JarFile(new File(resources, modifiedJarName),
    789                 true);
    790         Enumeration<JarEntry> entries = jarFile.entries();
    791         while (entries.hasMoreElements()) {
    792             ZipEntry zipEntry = entries.nextElement();
    793             try {
    794                 jarFile.getInputStream(zipEntry);
    795                 fail("should throw Security Exception");
    796             } catch (SecurityException e) {
    797                 // desired
    798             }
    799         }
    800     }
    801 
    802     /*
    803      * If the content of the .SA file is modified, no matter what it resides,
    804      * JarFile.getInputStream of any JarEntry will throw Security Exception.
    805      */
    806     public void test_JarFile_Modified_SF_EntryAttributes() throws IOException {
    807         String modifiedJarName = "Modified_SF_EntryAttributes.jar";
    808         Support_Resources.copyFile(resources, null, modifiedJarName);
    809         JarFile jarFile = new JarFile(new File(resources, modifiedJarName),
    810                 true);
    811         Enumeration<JarEntry> entries = jarFile.entries();
    812         while (entries.hasMoreElements()) {
    813             ZipEntry zipEntry = entries.nextElement();
    814             try {
    815                 jarFile.getInputStream(zipEntry);
    816                 fail("should throw Security Exception");
    817             } catch (SecurityException e) {
    818                 // desired
    819             }
    820         }
    821     }
    822 
    823     public void test_close() throws IOException {
    824         String modifiedJarName = "Modified_SF_EntryAttributes.jar";
    825         Support_Resources.copyFile(resources, null, modifiedJarName);
    826         JarFile jarFile = new JarFile(new File(resources, modifiedJarName),
    827                 true);
    828         Enumeration<JarEntry> entries = jarFile.entries();
    829 
    830         jarFile.close();
    831         jarFile.close();
    832 
    833         // Can not check IOException
    834     }
    835 
    836     /**
    837      * @throws IOException
    838      * java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)
    839      */
    840     public void test_getInputStreamLjava_util_jar_JarEntry() throws IOException {
    841         File localFile = null;
    842         try {
    843             Support_Resources.copyFile(resources, null, jarName);
    844             localFile = new File(resources, jarName);
    845         } catch (Exception e) {
    846             fail("Failed to create local file: " + e);
    847         }
    848 
    849         byte[] b = new byte[1024];
    850         try {
    851             JarFile jf = new JarFile(localFile);
    852             java.io.InputStream is = jf.getInputStream(jf.getEntry(entryName));
    853             // BEGIN android-removed
    854             // jf.close();
    855             // END android-removed
    856             assertTrue("Returned invalid stream", is.available() > 0);
    857             int r = is.read(b, 0, 1024);
    858             is.close();
    859             StringBuffer sb = new StringBuffer(r);
    860             for (int i = 0; i < r; i++) {
    861                 sb.append((char) (b[i] & 0xff));
    862             }
    863             String contents = sb.toString();
    864             assertTrue("Incorrect stream read", contents.indexOf("bar") > 0);
    865             // BEGIN android-added
    866             jf.close();
    867             // END android-added
    868         } catch (Exception e) {
    869             fail("Exception during test: " + e.toString());
    870         }
    871 
    872         try {
    873             JarFile jf = new JarFile(localFile);
    874             InputStream in = jf.getInputStream(new JarEntry("invalid"));
    875             assertNull("Got stream for non-existent entry", in);
    876         } catch (Exception e) {
    877             fail("Exception during test 2: " + e);
    878         }
    879 
    880         try {
    881             Support_Resources.copyFile(resources, null, jarName);
    882             File signedFile = new File(resources, jarName);
    883             JarFile jf = new JarFile(signedFile);
    884             JarEntry jre = new JarEntry("foo/bar/A.class");
    885             jf.getInputStream(jre);
    886             // InputStream returned in any way, exception can be thrown in case
    887             // of reading from this stream only.
    888             // fail("Should throw ZipException");
    889         } catch (ZipException ee) {
    890             // expected
    891         }
    892 
    893         try {
    894             Support_Resources.copyFile(resources, null, jarName);
    895             File signedFile = new File(resources, jarName);
    896             JarFile jf = new JarFile(signedFile);
    897             JarEntry jre = new JarEntry("foo/bar/A.class");
    898             jf.close();
    899             jf.getInputStream(jre);
    900             // InputStream returned in any way, exception can be thrown in case
    901             // of reading from this stream only.
    902             // The same for IOException
    903             fail("Should throw IllegalStateException");
    904         } catch (IllegalStateException ee) {
    905             // expected
    906         }
    907     }
    908 
    909     /**
    910      * The jar is intact, but the entry object is modified.
    911      */
    912     // Regression test for issue introduced by HARMONY-4569: signed archives containing files with size 0 could not get verified.
    913     public void testJarVerificationEmptyEntry() throws IOException {
    914         Support_Resources.copyFile(resources, null, emptyEntryJar);
    915         File f = new File(resources, emptyEntryJar);
    916 
    917         JarFile jarFile = new JarFile(f);
    918 
    919         ZipEntry zipEntry = jarFile.getJarEntry(emptyEntry1);
    920         int res = jarFile.getInputStream(zipEntry).read(new byte[100], 0, 100);
    921         assertEquals("Wrong length of empty jar entry", -1, res);
    922 
    923         zipEntry = jarFile.getJarEntry(emptyEntry2);
    924         res = jarFile.getInputStream(zipEntry).read(new byte[100], 0, 100);
    925         assertEquals("Wrong length of empty jar entry", -1, res);
    926 
    927         zipEntry = jarFile.getJarEntry(emptyEntry3);
    928         res = jarFile.getInputStream(zipEntry).read();
    929         assertEquals("Wrong length of empty jar entry", -1, res);
    930     }
    931 }
    932