0N/A/*
5516N/A * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.tools.java;
0N/A
0N/Aimport java.util.Enumeration;
0N/Aimport java.util.Hashtable;
0N/Aimport java.io.File;
0N/Aimport java.io.IOException;
0N/Aimport java.util.zip.*;
0N/A
0N/A/**
0N/A * This class is used to represent a class path, which can contain both
0N/A * directories and zip files.
0N/A *
0N/A * WARNING: The contents of this source file are not part of any
0N/A * supported API. Code that depends on them does so at its own risk:
0N/A * they are subject to change or removal without notice.
0N/A */
0N/Apublic
0N/Aclass ClassPath {
0N/A static final char dirSeparator = File.pathSeparatorChar;
0N/A
0N/A /**
0N/A * The original class path string
0N/A */
0N/A String pathstr;
0N/A
0N/A /**
0N/A * List of class path entries
0N/A */
0N/A private ClassPathEntry[] path;
0N/A
0N/A /**
0N/A * Build a class path from the specified path string
0N/A */
0N/A public ClassPath(String pathstr) {
0N/A init(pathstr);
0N/A }
0N/A
0N/A /**
0N/A * Build a class path from the specified array of class path
0N/A * element strings. This constructor, and the corresponding
0N/A * "init" method, were added as part of the fix for 6473331, which
0N/A * adds support for Class-Path manifest entries in JAR files to
0N/A * rmic. It is conceivable that the value of a Class-Path
0N/A * manifest entry will contain a path separator, which would cause
0N/A * incorrect behavior if the expanded path were passed to the
0N/A * previous constructor as a single path-separator-delimited
0N/A * string; use of this constructor avoids that problem.
0N/A */
0N/A public ClassPath(String[] patharray) {
0N/A init(patharray);
0N/A }
0N/A
0N/A /**
0N/A * Build a default class path from the path strings specified by
0N/A * the properties sun.boot.class.path and env.class.path, in that
0N/A * order.
0N/A */
0N/A public ClassPath() {
0N/A String syscp = System.getProperty("sun.boot.class.path");
0N/A String envcp = System.getProperty("env.class.path");
0N/A if (envcp == null) envcp = ".";
0N/A String cp = syscp + File.pathSeparator + envcp;
0N/A init(cp);
0N/A }
0N/A
0N/A private void init(String pathstr) {
0N/A int i, j, n;
0N/A // Save original class path string
0N/A this.pathstr = pathstr;
0N/A
0N/A if (pathstr.length() == 0) {
0N/A this.path = new ClassPathEntry[0];
0N/A }
0N/A
0N/A // Count the number of path separators
0N/A i = n = 0;
0N/A while ((i = pathstr.indexOf(dirSeparator, i)) != -1) {
0N/A n++; i++;
0N/A }
0N/A // Build the class path
0N/A ClassPathEntry[] path = new ClassPathEntry[n+1];
0N/A int len = pathstr.length();
0N/A for (i = n = 0; i < len; i = j + 1) {
0N/A if ((j = pathstr.indexOf(dirSeparator, i)) == -1) {
0N/A j = len;
0N/A }
0N/A if (i == j) {
0N/A path[n] = new ClassPathEntry();
0N/A path[n++].dir = new File(".");
0N/A } else {
0N/A File file = new File(pathstr.substring(i, j));
0N/A if (file.isFile()) {
0N/A try {
0N/A ZipFile zip = new ZipFile(file);
0N/A path[n] = new ClassPathEntry();
0N/A path[n++].zip = zip;
0N/A } catch (ZipException e) {
0N/A } catch (IOException e) {
0N/A // Ignore exceptions, at least for now...
0N/A }
0N/A } else {
0N/A path[n] = new ClassPathEntry();
0N/A path[n++].dir = file;
0N/A }
0N/A }
0N/A }
0N/A // Trim class path to exact size
0N/A this.path = new ClassPathEntry[n];
0N/A System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
0N/A }
0N/A
0N/A private void init(String[] patharray) {
0N/A // Save original class path string
0N/A if (patharray.length == 0) {
0N/A this.pathstr = "";
0N/A } else {
0N/A StringBuilder sb = new StringBuilder(patharray[0]);
0N/A for (int i = 1; i < patharray.length; i++) {
5516N/A sb.append(File.pathSeparatorChar);
0N/A sb.append(patharray[i]);
0N/A }
0N/A this.pathstr = sb.toString();
0N/A }
0N/A
0N/A // Build the class path
0N/A ClassPathEntry[] path = new ClassPathEntry[patharray.length];
0N/A int n = 0;
0N/A for (String name : patharray) {
0N/A File file = new File(name);
0N/A if (file.isFile()) {
0N/A try {
0N/A ZipFile zip = new ZipFile(file);
0N/A path[n] = new ClassPathEntry();
0N/A path[n++].zip = zip;
0N/A } catch (ZipException e) {
0N/A } catch (IOException e) {
0N/A // Ignore exceptions, at least for now...
0N/A }
0N/A } else {
0N/A path[n] = new ClassPathEntry();
0N/A path[n++].dir = file;
0N/A }
0N/A }
0N/A // Trim class path to exact size
0N/A this.path = new ClassPathEntry[n];
0N/A System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
0N/A }
0N/A
0N/A /**
0N/A * Find the specified directory in the class path
0N/A */
0N/A public ClassFile getDirectory(String name) {
0N/A return getFile(name, true);
0N/A }
0N/A
0N/A /**
0N/A * Load the specified file from the class path
0N/A */
0N/A public ClassFile getFile(String name) {
0N/A return getFile(name, false);
0N/A }
0N/A
0N/A private final String fileSeparatorChar = "" + File.separatorChar;
0N/A
0N/A private ClassFile getFile(String name, boolean isDirectory) {
0N/A String subdir = name;
0N/A String basename = "";
0N/A if (!isDirectory) {
0N/A int i = name.lastIndexOf(File.separatorChar);
0N/A subdir = name.substring(0, i + 1);
0N/A basename = name.substring(i + 1);
0N/A } else if (!subdir.equals("")
0N/A && !subdir.endsWith(fileSeparatorChar)) {
0N/A // zip files are picky about "foo" vs. "foo/".
0N/A // also, the getFiles caches are keyed with a trailing /
0N/A subdir = subdir + File.separatorChar;
0N/A name = subdir; // Note: isDirectory==true & basename==""
0N/A }
0N/A for (int i = 0; i < path.length; i++) {
0N/A if (path[i].zip != null) {
0N/A String newname = name.replace(File.separatorChar, '/');
0N/A ZipEntry entry = path[i].zip.getEntry(newname);
0N/A if (entry != null) {
0N/A return new ClassFile(path[i].zip, entry);
0N/A }
0N/A } else {
0N/A File file = new File(path[i].dir.getPath(), name);
0N/A String list[] = path[i].getFiles(subdir);
0N/A if (isDirectory) {
0N/A if (list.length > 0) {
0N/A return new ClassFile(file);
0N/A }
0N/A } else {
0N/A for (int j = 0; j < list.length; j++) {
0N/A if (basename.equals(list[j])) {
0N/A // Don't bother checking !file.isDir,
0N/A // since we only look for names which
0N/A // cannot already be packages (foo.java, etc).
0N/A return new ClassFile(file);
0N/A }
0N/A }
0N/A }
0N/A }
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A /**
0N/A * Returns list of files given a package name and extension.
0N/A */
0N/A public Enumeration getFiles(String pkg, String ext) {
0N/A Hashtable files = new Hashtable();
0N/A for (int i = path.length; --i >= 0; ) {
0N/A if (path[i].zip != null) {
0N/A Enumeration e = path[i].zip.entries();
0N/A while (e.hasMoreElements()) {
0N/A ZipEntry entry = (ZipEntry)e.nextElement();
0N/A String name = entry.getName();
0N/A name = name.replace('/', File.separatorChar);
0N/A if (name.startsWith(pkg) && name.endsWith(ext)) {
0N/A files.put(name, new ClassFile(path[i].zip, entry));
0N/A }
0N/A }
0N/A } else {
0N/A String[] list = path[i].getFiles(pkg);
0N/A for (int j = 0; j < list.length; j++) {
0N/A String name = list[j];
0N/A if (name.endsWith(ext)) {
0N/A name = pkg + File.separatorChar + name;
0N/A File file = new File(path[i].dir.getPath(), name);
0N/A files.put(name, new ClassFile(file));
0N/A }
0N/A }
0N/A }
0N/A }
0N/A return files.elements();
0N/A }
0N/A
0N/A /**
0N/A * Release resources.
0N/A */
0N/A public void close() throws IOException {
0N/A for (int i = path.length; --i >= 0; ) {
0N/A if (path[i].zip != null) {
0N/A path[i].zip.close();
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns original class path string
0N/A */
0N/A public String toString() {
0N/A return pathstr;
0N/A }
0N/A}
0N/A
0N/A/**
0N/A * A class path entry, which can either be a directory or an open zip file.
0N/A */
0N/Aclass ClassPathEntry {
0N/A File dir;
0N/A ZipFile zip;
0N/A
0N/A Hashtable subdirs = new Hashtable(29); // cache of sub-directory listings
0N/A String[] getFiles(String subdir) {
0N/A String files[] = (String[]) subdirs.get(subdir);
0N/A if (files == null) {
0N/A // search the directory, exactly once
0N/A File sd = new File(dir.getPath(), subdir);
0N/A if (sd.isDirectory()) {
0N/A files = sd.list();
0N/A if (files == null) {
0N/A // should not happen, but just in case, fail silently
0N/A files = new String[0];
0N/A }
0N/A if (files.length == 0) {
0N/A String nonEmpty[] = { "" };
0N/A files = nonEmpty;
0N/A }
0N/A } else {
0N/A files = new String[0];
0N/A }
0N/A subdirs.put(subdir, files);
0N/A }
0N/A return files;
0N/A }
0N/A
0N/A}