151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
248faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.misc;
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.*;
2948faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniakimport java.security.AccessController;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.*;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.jar.*;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.zip.*;
3348faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniakimport sun.security.action.GetPropertyAction;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This class is used to maintain mappings from packages, classes
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and resources to their enclosing JAR files. Mappings are kept
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * at the package level except for class or resource files that
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are located at the root directory. URLClassLoader uses the mapping
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * information to determine where to fetch an extension class or
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * resource from.
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author  Zhenghua Li
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since   1.3
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class JarIndex {
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The hash map that maintains mappings from
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * package/classe/resource to jar file list(s)
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
5348faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak    private HashMap<String,LinkedList<String>> indexMap;
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The hash map that maintains mappings from
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * jar file to package/class/resource lists
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
5948faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak    private HashMap<String,LinkedList<String>> jarMap;
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * An ordered list of jar file names.
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String[] jarFiles;
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The index file name.
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String INDEX_NAME = "META-INF/INDEX.LIST";
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * true if, and only if, sun.misc.JarIndex.metaInfFilenames is set to true.
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If true, the names of the files in META-INF, and its subdirectories, will
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * be added to the index. Otherwise, just the directory names are added.
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final boolean metaInfFilenames =
7748faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        "true".equals(AccessController.doPrivileged(
7848faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak             new GetPropertyAction("sun.misc.JarIndex.metaInfFilenames")));
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Constructs a new, empty jar index.
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public JarIndex() {
8448faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        indexMap = new HashMap<>();
8548faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        jarMap = new HashMap<>();
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Constructs a new index from the specified input stream.
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param is the input stream containing the index data
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public JarIndex(InputStream is) throws IOException {
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this();
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        read(is);
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Constructs a new index for the specified list of jar files.
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param files the list of jar files to construct the index from.
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public JarIndex(String[] files) throws IOException {
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this();
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.jarFiles = files;
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        parseJars(files);
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the jar index, or <code>null</code> if none.
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This single parameter version of the method is retained
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for binary compatibility with earlier releases.
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param jar the JAR file to get the index from.
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IOException if an I/O error has occurred.
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static JarIndex getJarIndex(JarFile jar) throws IOException {
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getJarIndex(jar, null);
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the jar index, or <code>null</code> if none.
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param jar the JAR file to get the index from.
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IOException if an I/O error has occurred.
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static JarIndex getJarIndex(JarFile jar, MetaIndex metaIndex) throws IOException {
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JarIndex index = null;
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* If metaIndex is not null, check the meta index to see
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski           if META-INF/INDEX.LIST is contained in jar file or not.
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        */
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (metaIndex != null &&
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            !metaIndex.mayContain(INDEX_NAME)) {
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JarEntry e = jar.getJarEntry(INDEX_NAME);
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if found, then load the index
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (e != null) {
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            index = new JarIndex(jar.getInputStream(e));
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return index;
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the jar files that are defined in this index.
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String[] getJarFiles() {
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return jarFiles;
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Add the key, value pair to the hashmap, the value will
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * be put in a linked list which is created if necessary.
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
15648faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak    private void addToList(String key, String value,
15748faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                           HashMap<String,LinkedList<String>> t) {
15848faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        LinkedList<String> list = t.get(key);
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (list == null) {
16048faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak            list = new LinkedList<>();
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            list.add(value);
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            t.put(key, list);
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (!list.contains(value)) {
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            list.add(value);
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the list of jar files that are mapped to the file.
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param fileName the key of the mapping
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
17348faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak    public LinkedList<String> get(String fileName) {
17448faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        LinkedList<String> jarFiles = null;
17548faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        if ((jarFiles = indexMap.get(fileName)) == null) {
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* try the package name again */
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int pos;
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if((pos = fileName.lastIndexOf("/")) != -1) {
17948faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                jarFiles = indexMap.get(fileName.substring(0, pos));
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return jarFiles;
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Add the mapping from the specified file to the specified
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * jar file. If there were no mapping for the package of the
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * specified file before, a new linked list will be created,
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the jar file is added to the list and a new mapping from
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the package to the jar file list is added to the hashmap.
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Otherwise, the jar file will be added to the end of the
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * existing list.
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param fileName the file name
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param jarName the jar file that the file is mapped to
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void add(String fileName, String jarName) {
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String packageName;
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int pos;
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if((pos = fileName.lastIndexOf("/")) != -1) {
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            packageName = fileName.substring(0, pos);
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            packageName = fileName;
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20748faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        addMapping(packageName, jarName);
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Same as add(String,String) except that it doesn't strip off from the
21248faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak     * last index of '/'. It just adds the jarItem (filename or package)
21348faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak     * as it is received.
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
21548faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak    private void addMapping(String jarItem, String jarName) {
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // add the mapping to indexMap
21748faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        addToList(jarItem, jarName, indexMap);
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // add the mapping to jarMap
22048faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        addToList(jarName, jarItem, jarMap);
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     }
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Go through all the jar files and construct the
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * index table.
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void parseJars(String[] files) throws IOException {
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (files == null) {
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String currentJar = null;
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < files.length; i++) {
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            currentJar = files[i];
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ZipFile zrf = new ZipFile(currentJar.replace
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                      ('/', File.separatorChar));
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23948faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak            Enumeration<? extends ZipEntry> entries = zrf.entries();
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while(entries.hasMoreElements()) {
24148faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                ZipEntry entry = entries.nextElement();
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String fileName = entry.getName();
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Skip the META-INF directory, the index, and manifest.
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Any files in META-INF/ will be indexed explicitly
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (fileName.equals("META-INF/") ||
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    fileName.equals(INDEX_NAME) ||
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    fileName.equals(JarFile.MANIFEST_NAME))
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    continue;
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25148faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                if (!metaInfFilenames || !fileName.startsWith("META-INF/")) {
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    add(fileName, currentJar);
25348faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                } else if (!entry.isDirectory()) {
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // Add files under META-INF explicitly so that certain
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // services, like ServiceLoader, etc, can be located
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // with greater accuracy. Directories can be skipped
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // since each file will be added explicitly.
25848faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                        addMapping(fileName, currentJar);
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            zrf.close();
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Writes the index to the specified OutputStream
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param out the output stream
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IOException if an I/O error has occurred
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void write(OutputStream out) throws IOException {
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        BufferedWriter bw = new BufferedWriter
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            (new OutputStreamWriter(out, "UTF8"));
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bw.write("JarIndex-Version: 1.0\n\n");
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (jarFiles != null) {
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < jarFiles.length; i++) {
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /* print out the jar file name */
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String jar = jarFiles[i];
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bw.write(jar + "\n");
28248faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                LinkedList<String> jarlist = jarMap.get(jar);
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (jarlist != null) {
28448faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                    Iterator<String> listitr = jarlist.iterator();
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    while(listitr.hasNext()) {
28648faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                        bw.write(listitr.next() + "\n");
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bw.write("\n");
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bw.flush();
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads the index from the specified InputStream.
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param is the input stream
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IOException if an I/O error has occurred
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void read(InputStream is) throws IOException {
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        BufferedReader br = new BufferedReader
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            (new InputStreamReader(is, "UTF8"));
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String line = null;
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String currentJar = null;
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* an ordered list of jar file names */
30948faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        Vector<String> jars = new Vector<>();
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* read until we see a .jar line */
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while((line = br.readLine()) != null && !line.endsWith(".jar"));
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for(;line != null; line = br.readLine()) {
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (line.length() == 0)
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                continue;
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (line.endsWith(".jar")) {
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                currentJar = line;
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                jars.add(currentJar);
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String name = line;
32348faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                addMapping(name, currentJar);
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32748faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        jarFiles = jars.toArray(new String[jars.size()]);
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Merges the current index into another index, taking into account
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the relative path of the current index.
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param toIndex The destination index which the current index will
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                merge into.
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param path    The relative path of the this index to the destination
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                index.
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void merge(JarIndex toIndex, String path) {
34148faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak        Iterator<Map.Entry<String,LinkedList<String>>> itr = indexMap.entrySet().iterator();
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while(itr.hasNext()) {
34348faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak            Map.Entry<String,LinkedList<String>> e = itr.next();
34448faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak            String packageName = e.getKey();
34548faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak            LinkedList<String> from_list = e.getValue();
34648faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak            Iterator<String> listItr = from_list.iterator();
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while(listItr.hasNext()) {
34848faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                String jarName = listItr.next();
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (path != null) {
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    jarName = path.concat(jarName);
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
35248faf4ee21028b39dac2b459f0b560d743426801Przemyslaw Szczepaniak                toIndex.addMapping(packageName, jarName);
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
357