All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.jdk.compiler.share.classes.com.sun.tools.javac.file.Locations Maven / Gradle / Ivy

Go to download

"nb-javac" is a patched version of OpenJDK "javac", i.e., the Java compiler. This has long been part of NetBeans, providing a highly tuned Java compiler specifically for the Java editor i.e., parsing and lexing for features such as syntax coloring, code completion.

There is a newer version: 17.0.0.0
Show newest version
/*
 * Copyright (c) 2003, 2021, 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 com.sun.tools.javac.file;

import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.DirectoryIteratorException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystemNotFoundException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.ProviderNotFoundException;
import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import javax.lang.model.SourceVersion;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileManager.Location;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardJavaFileManager.PathFactory;
import javax.tools.StandardLocation;

import nbjavac.JmodFileWrapper;

import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.JCDiagnostic.Warning;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.jvm.ModuleNameReader;
import com.sun.tools.javac.util.Iterators;
import com.sun.tools.javac.util.Pair;
import com.sun.tools.javac.util.StringUtils;

import static javax.tools.StandardLocation.SYSTEM_MODULES;
import static javax.tools.StandardLocation.PLATFORM_CLASS_PATH;

import static com.sun.tools.javac.main.Option.BOOT_CLASS_PATH;
import static com.sun.tools.javac.main.Option.ENDORSEDDIRS;
import static com.sun.tools.javac.main.Option.EXTDIRS;
import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH_APPEND;
import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH_PREPEND;

/**
 * This class converts command line arguments, environment variables and system properties (in
 * File.pathSeparator-separated String form) into a boot class path, user class path, and source
 * path (in {@code Collection} form).
 *
 * 

* This is NOT part of any supported API. If you write code that depends on this, you do so at * your own risk. This code and its internal interfaces are subject to change or deletion without * notice. */ public class Locations { /** * The log to use for warning output */ private Log log; /** * Access to (possibly cached) file info */ private FSInfo fsInfo; /** * Whether to warn about non-existent path elements */ private boolean warn; private ModuleNameReader moduleNameReader; private PathFactory pathFactory = Paths::get; static final Path javaHome = FileSystems.getDefault().getPath(System.getProperty("java.home")); static final Path thisSystemModules = javaHome.resolve("lib").resolve("modules"); Map fileSystems = new LinkedHashMap<>(); List closeables = new ArrayList<>(); private Map fsEnv = Collections.emptyMap(); Locations() { initHandlers(); } Path getPath(String first, String... more) { try { return pathFactory.getPath(first, more); } catch (InvalidPathException ipe) { throw new IllegalArgumentException(ipe); } } public void close() throws IOException { ListBuffer list = new ListBuffer<>(); closeables.forEach(closeable -> { try { closeable.close(); } catch (IOException ex) { list.add(ex); } }); if (list.nonEmpty()) { IOException ex = new IOException(); for (IOException e: list) ex.addSuppressed(e); throw ex; } } void update(Log log, boolean warn, FSInfo fsInfo) { this.log = log; this.warn = warn; this.fsInfo = fsInfo; } void setPathFactory(PathFactory f) { pathFactory = f; } boolean isDefaultBootClassPath() { BootClassPathLocationHandler h = (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH); return h.isDefault(); } boolean isDefaultSystemModulesPath() { SystemModulesLocationHandler h = (SystemModulesLocationHandler) getHandler(SYSTEM_MODULES); return !h.isExplicit(); } /** * Split a search path into its elements. Empty path elements will be ignored. * * @param searchPath The search path to be split * @return The elements of the path */ private Iterable getPathEntries(String searchPath) { return getPathEntries(searchPath, null); } /** * Split a search path into its elements. If emptyPathDefault is not null, all empty elements in the * path, including empty elements at either end of the path, will be replaced with the value of * emptyPathDefault. * * @param searchPath The search path to be split * @param emptyPathDefault The value to substitute for empty path elements, or null, to ignore * empty path elements * @return The elements of the path */ private Iterable getPathEntries(String searchPath, Path emptyPathDefault) { ListBuffer entries = new ListBuffer<>(); for (String s: searchPath.split(Pattern.quote(File.pathSeparator), -1)) { if (s.isEmpty()) { if (emptyPathDefault != null) { entries.add(emptyPathDefault); } } else { try { entries.add(getPath(s)); } catch (IllegalArgumentException e) { if (warn) { log.warning(LintCategory.PATH, Warnings.InvalidPath(s)); } } } } return entries; } public void setMultiReleaseValue(String multiReleaseValue) { fsEnv = Collections.singletonMap("releaseVersion", multiReleaseValue); } private boolean contains(Collection searchPath, Path file) throws IOException { if (searchPath == null) { return false; } Path enclosingJar = null; if (file.getFileSystem().provider() == fsInfo.getJarFSProvider()) { URI uri = file.toUri(); if (uri.getScheme().equals("jar")) { String ssp = uri.getSchemeSpecificPart(); int sep = ssp.lastIndexOf("!"); if (ssp.startsWith("file:") && sep > 0) { enclosingJar = Paths.get(URI.create(ssp.substring(0, sep))); } } } Path nf = normalize(file); for (Path p : searchPath) { Path np = normalize(p); if (np.getFileSystem() == nf.getFileSystem() && Files.isDirectory(np) && nf.startsWith(np)) { return true; } if (enclosingJar != null && Files.isSameFile(enclosingJar, np)) { return true; } } return false; } /** * Utility class to help evaluate a path option. Duplicate entries are ignored, jar class paths * can be expanded. */ private class SearchPath extends LinkedHashSet { private static final long serialVersionUID = 0; private boolean expandJarClassPaths = false; private final transient Set canonicalValues = new HashSet<>(); public SearchPath expandJarClassPaths(boolean x) { expandJarClassPaths = x; return this; } /** * What to use when path element is the empty string */ private transient Path emptyPathDefault = null; public SearchPath emptyPathDefault(Path x) { emptyPathDefault = x; return this; } public SearchPath addDirectories(String dirs, boolean warn) { boolean prev = expandJarClassPaths; expandJarClassPaths = true; try { if (dirs != null) { for (Path dir : getPathEntries(dirs)) { addDirectory(dir, warn); } } return this; } finally { expandJarClassPaths = prev; } } public SearchPath addDirectories(String dirs) { return addDirectories(dirs, warn); } private void addDirectory(Path dir, boolean warn) { if (!Files.isDirectory(dir)) { if (warn) { log.warning(Lint.LintCategory.PATH, Warnings.DirPathElementNotFound(dir)); } return; } try (Stream s = Files.list(dir)) { s.filter(Locations.this::isArchive) .forEach(dirEntry -> addFile(dirEntry, warn)); } catch (IOException ignore) { } } public SearchPath addFiles(String files, boolean warn) { if (files != null) { addFiles(getPathEntries(files, emptyPathDefault), warn); } return this; } public SearchPath addFiles(String files) { return addFiles(files, warn); } public SearchPath addFiles(Iterable files, boolean warn) { if (files != null) { for (Path file : files) { addFile(file, warn); } } return this; } public SearchPath addFiles(Iterable files) { return addFiles(files, warn); } public void addFile(Path file, boolean warn) { if (contains(file)) { // discard duplicates return; } if (!fsInfo.exists(file)) { /* No such file or directory exists */ if (warn) { log.warning(Lint.LintCategory.PATH, Warnings.PathElementNotFound(file)); } super.add(file); return; } Path canonFile = fsInfo.getCanonicalFile(file); if (canonicalValues.contains(canonFile)) { /* Discard duplicates and avoid infinite recursion */ return; } if (fsInfo.isFile(file)) { /* File is an ordinary file. */ if ( !file.getFileName().toString().endsWith(".jmod") && !file.endsWith("modules")) { if (!isArchive(file)) { /* Not a recognized extension; open it to see if it looks like a valid zip file. */ try { FileSystems.newFileSystem(file, (ClassLoader)null).close(); if (warn) { log.warning(Lint.LintCategory.PATH, Warnings.UnexpectedArchiveFile(file)); } } catch (IOException | ProviderNotFoundException e) { // FIXME: include e.getLocalizedMessage in warning if (warn) { log.warning(Lint.LintCategory.PATH, Warnings.InvalidArchiveFile(file)); } return; } } else { if (fsInfo.getJarFSProvider() == null) { log.error(Errors.NoZipfsForArchive(file)); return ; } } } } /* Now what we have left is either a directory or a file name conforming to archive naming convention */ super.add(file); canonicalValues.add(canonFile); if (expandJarClassPaths && fsInfo.isFile(file) && !file.endsWith("modules")) { addJarClassPath(file, warn); } } // Adds referenced classpath elements from a jar's Class-Path // Manifest entry. In some future release, we may want to // update this code to recognize URLs rather than simple // filenames, but if we do, we should redo all path-related code. private void addJarClassPath(Path jarFile, boolean warn) { try { for (Path f : fsInfo.getJarClassPath(jarFile)) { addFile(f, warn); } } catch (IOException e) { log.error(Errors.ErrorReadingFile(jarFile, JavacFileManager.getMessage(e))); } } } /** * Base class for handling support for the representation of Locations. * * Locations are (by design) opaque handles that can easily be implemented * by enums like StandardLocation. Within JavacFileManager, each Location * has an associated LocationHandler, which provides much of the appropriate * functionality for the corresponding Location. * * @see #initHandlers * @see #getHandler */ protected abstract static class LocationHandler { /** * @see JavaFileManager#handleOption */ abstract boolean handleOption(Option option, String value); /** * @see StandardJavaFileManager#hasLocation */ boolean isSet() { return (getPaths() != null); } abstract boolean isExplicit(); /** * @see StandardJavaFileManager#getLocation */ abstract Collection getPaths(); /** * @see StandardJavaFileManager#setLocation */ abstract void setPaths(Iterable paths) throws IOException; /** * @see StandardJavaFileManager#setLocationForModule */ abstract void setPathsForModule(String moduleName, Iterable paths) throws IOException; /** * @see JavaFileManager#getLocationForModule(Location, String) */ Location getLocationForModule(String moduleName) throws IOException { return null; } /** * @see JavaFileManager#getLocationForModule(Location, JavaFileObject, String) */ Location getLocationForModule(Path file) throws IOException { return null; } /** * @see JavaFileManager#inferModuleName */ String inferModuleName() { return null; } /** * @see JavaFileManager#listLocationsForModules */ Iterable> listLocationsForModules() throws IOException { return null; } /** * @see JavaFileManager#contains */ abstract boolean contains(Path file) throws IOException; } /** * A LocationHandler for a given Location, and associated set of options. */ private abstract static class BasicLocationHandler extends LocationHandler { final Location location; final Set





© 2015 - 2024 Weber Informatics LLC | Privacy Policy