Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/java/ClassPath.java
38918 views
/*1* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.java;2627import java.util.Enumeration;28import java.util.Hashtable;29import java.io.File;30import java.io.IOException;31import java.util.zip.*;3233/**34* This class is used to represent a class path, which can contain both35* directories and zip files.36*37* WARNING: The contents of this source file are not part of any38* supported API. Code that depends on them does so at its own risk:39* they are subject to change or removal without notice.40*/41public42class ClassPath {43static final char dirSeparator = File.pathSeparatorChar;4445/**46* The original class path string47*/48String pathstr;4950/**51* List of class path entries52*/53private ClassPathEntry[] path;5455/**56* Build a class path from the specified path string57*/58public ClassPath(String pathstr) {59init(pathstr);60}6162/**63* Build a class path from the specified array of class path64* element strings. This constructor, and the corresponding65* "init" method, were added as part of the fix for 6473331, which66* adds support for Class-Path manifest entries in JAR files to67* rmic. It is conceivable that the value of a Class-Path68* manifest entry will contain a path separator, which would cause69* incorrect behavior if the expanded path were passed to the70* previous constructor as a single path-separator-delimited71* string; use of this constructor avoids that problem.72*/73public ClassPath(String[] patharray) {74init(patharray);75}7677/**78* Build a default class path from the path strings specified by79* the properties sun.boot.class.path and env.class.path, in that80* order.81*/82public ClassPath() {83String syscp = System.getProperty("sun.boot.class.path");84String envcp = System.getProperty("env.class.path");85if (envcp == null) envcp = ".";86String cp = syscp + File.pathSeparator + envcp;87init(cp);88}8990private void init(String pathstr) {91int i, j, n;92// Save original class path string93this.pathstr = pathstr;9495if (pathstr.length() == 0) {96this.path = new ClassPathEntry[0];97}9899// Count the number of path separators100i = n = 0;101while ((i = pathstr.indexOf(dirSeparator, i)) != -1) {102n++; i++;103}104// Build the class path105ClassPathEntry[] path = new ClassPathEntry[n+1];106int len = pathstr.length();107for (i = n = 0; i < len; i = j + 1) {108if ((j = pathstr.indexOf(dirSeparator, i)) == -1) {109j = len;110}111if (i == j) {112path[n] = new ClassPathEntry();113path[n++].dir = new File(".");114} else {115File file = new File(pathstr.substring(i, j));116if (file.isFile()) {117try {118ZipFile zip = new ZipFile(file);119path[n] = new ClassPathEntry();120path[n++].zip = zip;121} catch (ZipException e) {122} catch (IOException e) {123// Ignore exceptions, at least for now...124}125} else {126path[n] = new ClassPathEntry();127path[n++].dir = file;128}129}130}131// Trim class path to exact size132this.path = new ClassPathEntry[n];133System.arraycopy((Object)path, 0, (Object)this.path, 0, n);134}135136private void init(String[] patharray) {137// Save original class path string138if (patharray.length == 0) {139this.pathstr = "";140} else {141StringBuilder sb = new StringBuilder(patharray[0]);142for (int i = 1; i < patharray.length; i++) {143sb.append(File.pathSeparatorChar);144sb.append(patharray[i]);145}146this.pathstr = sb.toString();147}148149// Build the class path150ClassPathEntry[] path = new ClassPathEntry[patharray.length];151int n = 0;152for (String name : patharray) {153File file = new File(name);154if (file.isFile()) {155try {156ZipFile zip = new ZipFile(file);157path[n] = new ClassPathEntry();158path[n++].zip = zip;159} catch (ZipException e) {160} catch (IOException e) {161// Ignore exceptions, at least for now...162}163} else {164path[n] = new ClassPathEntry();165path[n++].dir = file;166}167}168// Trim class path to exact size169this.path = new ClassPathEntry[n];170System.arraycopy((Object)path, 0, (Object)this.path, 0, n);171}172173/**174* Find the specified directory in the class path175*/176public ClassFile getDirectory(String name) {177return getFile(name, true);178}179180/**181* Load the specified file from the class path182*/183public ClassFile getFile(String name) {184return getFile(name, false);185}186187private final String fileSeparatorChar = "" + File.separatorChar;188189private ClassFile getFile(String name, boolean isDirectory) {190String subdir = name;191String basename = "";192if (!isDirectory) {193int i = name.lastIndexOf(File.separatorChar);194subdir = name.substring(0, i + 1);195basename = name.substring(i + 1);196} else if (!subdir.equals("")197&& !subdir.endsWith(fileSeparatorChar)) {198// zip files are picky about "foo" vs. "foo/".199// also, the getFiles caches are keyed with a trailing /200subdir = subdir + File.separatorChar;201name = subdir; // Note: isDirectory==true & basename==""202}203for (int i = 0; i < path.length; i++) {204if (path[i].zip != null) {205String newname = name.replace(File.separatorChar, '/');206ZipEntry entry = path[i].zip.getEntry(newname);207if (entry != null) {208return new ClassFile(path[i].zip, entry);209}210} else {211File file = new File(path[i].dir.getPath(), name);212String list[] = path[i].getFiles(subdir);213if (isDirectory) {214if (list.length > 0) {215return new ClassFile(file);216}217} else {218for (int j = 0; j < list.length; j++) {219if (basename.equals(list[j])) {220// Don't bother checking !file.isDir,221// since we only look for names which222// cannot already be packages (foo.java, etc).223return new ClassFile(file);224}225}226}227}228}229return null;230}231232/**233* Returns list of files given a package name and extension.234*/235public Enumeration getFiles(String pkg, String ext) {236Hashtable files = new Hashtable();237for (int i = path.length; --i >= 0; ) {238if (path[i].zip != null) {239Enumeration e = path[i].zip.entries();240while (e.hasMoreElements()) {241ZipEntry entry = (ZipEntry)e.nextElement();242String name = entry.getName();243name = name.replace('/', File.separatorChar);244if (name.startsWith(pkg) && name.endsWith(ext)) {245files.put(name, new ClassFile(path[i].zip, entry));246}247}248} else {249String[] list = path[i].getFiles(pkg);250for (int j = 0; j < list.length; j++) {251String name = list[j];252if (name.endsWith(ext)) {253name = pkg + File.separatorChar + name;254File file = new File(path[i].dir.getPath(), name);255files.put(name, new ClassFile(file));256}257}258}259}260return files.elements();261}262263/**264* Release resources.265*/266public void close() throws IOException {267for (int i = path.length; --i >= 0; ) {268if (path[i].zip != null) {269path[i].zip.close();270}271}272}273274/**275* Returns original class path string276*/277public String toString() {278return pathstr;279}280}281282/**283* A class path entry, which can either be a directory or an open zip file.284*/285class ClassPathEntry {286File dir;287ZipFile zip;288289Hashtable subdirs = new Hashtable(29); // cache of sub-directory listings290String[] getFiles(String subdir) {291String files[] = (String[]) subdirs.get(subdir);292if (files == null) {293// search the directory, exactly once294File sd = new File(dir.getPath(), subdir);295if (sd.isDirectory()) {296files = sd.list();297if (files == null) {298// should not happen, but just in case, fail silently299files = new String[0];300}301if (files.length == 0) {302String nonEmpty[] = { "" };303files = nonEmpty;304}305} else {306files = new String[0];307}308subdirs.put(subdir, files);309}310return files;311}312313}314315316