/* * (C) Copyright 2005, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package org.nuxeo.runtime.osgi.util.jar.index; import java.io.File; import java.io.IOException; import java.util.Enumeration; import java.util.HashSet; import java.util.jar.JarEntry; import java.util.jar.JarFile; /* * JarMetaIndex associates the jar file with a set of what so called * "meta-index" of the jar file. Essentially, the meta-index is a list * of class prefixes and the plain files contained in META-INF directory ( * not include the manifest file itself). This will help sun.misc.URLClassPath * to quickly locate the resource file and hotspot VM to locate the class file. * */ class JarMetaIndex { protected File file; private volatile HashSet<String> indexSet; private JarFileKind jarFileKind; public JarMetaIndex(String fileName) throws IOException { file = new File(fileName); } /* Returns a HashSet contains the meta index string. */ HashSet<String> getMetaIndex() throws IOException { if (indexSet == null) { synchronized (this) { if (indexSet != null) { return indexSet; } indexSet = new HashSet<String>(); JarFile jar = new JarFile(file); try { Enumeration<JarEntry> entries = jar.entries(); boolean containsOnlyClass = true; boolean containsOnlyResource = true; while (entries.hasMoreElements()) { JarEntry entry = (JarEntry) entries.nextElement(); String name = entry.getName(); /* * We only look at the non-directory entry. MANIFEST file is also skipped. */ if (entry.isDirectory() || name.equals("META-INF/MANIFEST.MF")) { continue; } /* * Once containsOnlyResource or containsOnlyClass turns to false, no need to check the entry * type. */ if (containsOnlyResource || containsOnlyClass) { if (name.endsWith(".class")) { containsOnlyResource = false; } else { containsOnlyClass = false; } } /* * Add the full-qualified name of plain files under META-INF directory to the indexSet. */ if (name.startsWith("META-INF")) { indexSet.add(name); continue; } String[] pkgElements = name.split("/"); // Last one is the class name; definitely ignoring that if (pkgElements.length > 2) { String meta = null; // Need more information than just first two package // name elements to determine that classes in // deploy.jar are not in rt.jar if (pkgElements.length > 3 && pkgElements[0].equals("com") && pkgElements[1].equals("sun")) { // Need more precise information to disambiguate // (illegal) references from applications to // obsolete backported collections classes in // com/sun/java/util if (pkgElements.length > 4 && pkgElements[2].equals("java")) { int bound = 0; if (pkgElements[3].equals("util")) { // Take all of the packages bound = pkgElements.length - 1; } else { // Trim it somewhat more bound = 4; } meta = ""; for (int j = 0; j < bound; j++) { meta += pkgElements[j] + "/"; } } else { meta = pkgElements[0] + "/" + pkgElements[1] + "/" + pkgElements[2] + "/"; } } else { meta = pkgElements[0] + "/" + pkgElements[1] + "/"; } indexSet.add(meta); } } // end of "while" loop; /* Set "jarFileKind" attribute. */ if (containsOnlyClass) { jarFileKind = JarFileKind.CLASSONLY; } else if (containsOnlyResource) { jarFileKind = JarFileKind.RESOURCEONLY; } else { jarFileKind = JarFileKind.MIXED; } } finally { jar.close(); } } } return indexSet; } JarFileKind getJarFileKind() throws IOException { // Build meta index if it hasn't. if (indexSet == null) { indexSet = getMetaIndex(); } return jarFileKind; } }