/*
 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/**
 * @test
 * @bug 8031572
 * @summary jarsigner -verify exits with 0 when a jar file is not properly signed
 */

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.cert.Certificate;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class EntriesOrder {

    public static void main(String[] args) throws Exception {

        String[] entries = {
                "META-INF/",
                "META-INF/MANIFEST.MF",
                "META-INF/A.RSA",
                "META-INF/A.SF",
                "META-INF/inf",
                "a"};

        Map<String,byte[]> content = new HashMap<>();

        // We will create a jar containing entries above. Try all permutations
        // and confirm 1) When opened as a JarFile, we can always get 3 signed
        // ones (MANIFEST, inf, a), and 2) When opened as a JarInputStream,
        // when the order is correct (MANIFEST at beginning, followed by RSA/SF,
        // directory ignored), we can get 2 signed ones (inf, a).

        // Prepares raw files
        Files.write(Paths.get("a"), "a".getBytes());
        Files.createDirectory(Paths.get("META-INF/"));
        Files.write(Paths.get("META-INF/inf"), "inf".getBytes());

        // Pack, sign, and extract to get all files
        sun.tools.jar.Main m =
                new sun.tools.jar.Main(System.out, System.err, "jar");
        if (!m.run("cvf a.jar a META-INF/inf".split(" "))) {
            throw new Exception("jar creation failed");
        }
        sun.security.tools.keytool.Main.main(
                ("-keystore jks -storepass changeit -keypass changeit -dname" +
                        " CN=A -alias a -genkeypair -keyalg rsa").split(" "));
        sun.security.tools.jarsigner.Main.main(
                "-keystore jks -storepass changeit a.jar a".split(" "));
        m = new sun.tools.jar.Main(System.out, System.err, "jar");
        if (!m.run("xvf a.jar".split(" "))) {
            throw new Exception("jar extraction failed");
        }

        // Data
        for (String s: entries) {
            if (!s.endsWith("/")) {
                content.put(s, Files.readAllBytes(Paths.get(s)));
            }
        }

        // Test
        for (List<String> perm: Permute(entries)) {

            // Recreate a jar
            try (ZipOutputStream zos
                         = new ZipOutputStream(new FileOutputStream("x.jar"))) {
                for (String e: perm) {
                    zos.putNextEntry(new ZipEntry(e));
                    if (Paths.get(e).toFile().isDirectory()) continue;
                    zos.write(content.get(e));
                }
            }

            // Open with JarFile, number of signed entries should be 3.
            int cc = 0;
            try (JarFile jf = new JarFile("x.jar")) {
                Enumeration<JarEntry> jes = jf.entries();
                while (jes.hasMoreElements()) {
                    JarEntry je = jes.nextElement();
                    sun.misc.IOUtils.readFully(jf.getInputStream(je), -1, true);
                    Certificate[] certs = je.getCertificates();
                    if (certs != null && certs.length > 0) {
                        cc++;
                    }
                }
            }

            if (cc != 3) {
                System.out.println(perm + " - jf - " + cc);
                throw new Exception();
            }

            // Open with JarInputStream
            int signed;

            perm.remove("META-INF/");
            if (perm.get(0).equals("META-INF/MANIFEST.MF") &&
                    perm.get(1).contains("/A.") &&
                    perm.get(2).contains("/A.")) {
                signed = 2;     // Good order
            } else {
                signed = 0;     // Bad order. In this case, the number of signed
                                // entries is not documented. Just test impl.
            }

            cc = 0;
            try (JarInputStream jis
                         = new JarInputStream(new FileInputStream("x.jar"))) {
                while (true) {
                    JarEntry je = jis.getNextJarEntry();
                    if (je == null) break;
                    sun.misc.IOUtils.readFully(jis, -1, true);
                    Certificate[] certs = je.getCertificates();
                    if (certs != null && certs.length > 0) {
                        cc++;
                    }
                }
            }

            if (cc != signed) {
                System.out.println(perm + " - jis - " + cc + " " + signed);
                throw new Exception();
            }
        }
    }

    // Helper method to return all permutations of an array. Each output can
    // be altered without damaging the iteration process.
    static Iterable<List<String>> Permute(String[] entries) {
        return new Iterable<List<String>>() {

            int s = entries.length;
            long c = factorial(s) - 1;      // number of permutations

            private long factorial(int n) {
                return (n == 1) ? 1: (n * factorial(n-1));
            }

            @Override
            public Iterator<List<String>> iterator() {
                return new Iterator<List<String>>() {
                    @Override
                    public boolean hasNext() {
                        return c >= 0;
                    }

                    @Override
                    public List<String> next() {
                        if (c < 0) return null;
                        List<String> result = new ArrayList<>(s);
                        LinkedList<String> source = new LinkedList<>(
                                Arrays.asList(entries));
                        // Treat c as a integer with different radixes at
                        // different digits, i.e. at digit 0, radix is s;
                        // at digit 1, radix is s-1. Thus a s-digit number
                        // is able to represent s! different values.
                        long n = c;
                        for (int i=s; i>=1; i--) {
                            int x = (int)(n % i);
                            result.add(source.remove(x));
                            n = n / i;
                        }
                        c--;
                        return result;
                    }
                };
            }
        };
    }
}
