mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-12 06:29:37 +00:00
8059976: Convert JavacFileManager to use java.nio.file internally
Reviewed-by: jlahoda
This commit is contained in:
parent
4297432f73
commit
31cdc1ad3d
@ -343,7 +343,7 @@ public class ClassFinder {
|
||||
}
|
||||
currentClassFile = classfile;
|
||||
if (verbose) {
|
||||
log.printVerbose("loading", currentClassFile.toString());
|
||||
log.printVerbose("loading", currentClassFile.getName());
|
||||
}
|
||||
if (classfile.getKind() == JavaFileObject.Kind.CLASS ||
|
||||
classfile.getKind() == JavaFileObject.Kind.OTHER) {
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2014, 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.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.NestingKind;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.util.DefinedBy;
|
||||
import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
|
||||
/**
|
||||
* <p><b>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.</b>
|
||||
*/
|
||||
public abstract class BaseFileObject implements JavaFileObject {
|
||||
protected BaseFileObject(JavacFileManager fileManager) {
|
||||
this.fileManager = fileManager;
|
||||
}
|
||||
|
||||
/** Return a short name for the object, such as for use in raw diagnostics
|
||||
*/
|
||||
public abstract String getShortName();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "[" + getName() + "]";
|
||||
}
|
||||
|
||||
@DefinedBy(Api.COMPILER)
|
||||
public NestingKind getNestingKind() { return null; }
|
||||
|
||||
@DefinedBy(Api.COMPILER)
|
||||
public Modifier getAccessLevel() { return null; }
|
||||
|
||||
@DefinedBy(Api.COMPILER)
|
||||
public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
|
||||
return new InputStreamReader(openInputStream(), getDecoder(ignoreEncodingErrors));
|
||||
}
|
||||
|
||||
protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected abstract String inferBinaryName(Iterable<? extends Path> path);
|
||||
|
||||
protected static JavaFileObject.Kind getKind(String filename) {
|
||||
return BaseFileManager.getKind(filename);
|
||||
}
|
||||
|
||||
protected static String removeExtension(String fileName) {
|
||||
int lastDot = fileName.lastIndexOf(".");
|
||||
return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
|
||||
}
|
||||
|
||||
protected static URI createJarUri(Path jarFile, String entryName) {
|
||||
URI jarURI = jarFile.toUri().normalize();
|
||||
String separator = entryName.startsWith("/") ? "!" : "!/";
|
||||
try {
|
||||
// The jar URI convention appears to be not to re-encode the jarURI
|
||||
return new URI("jar:" + jarURI + separator + entryName);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new CannotCreateUriError(jarURI + separator + entryName, e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Used when URLSyntaxException is thrown unexpectedly during
|
||||
* implementations of (Base)FileObject.toURI(). */
|
||||
protected static class CannotCreateUriError extends Error {
|
||||
private static final long serialVersionUID = 9101708840997613546L;
|
||||
public CannotCreateUriError(String value, Throwable cause) {
|
||||
super(value, cause);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the last component of a presumed hierarchical URI.
|
||||
* From the scheme specific part of the URI, it returns the substring
|
||||
* after the last "/" if any, or everything if no "/" is found.
|
||||
*/
|
||||
public static String getSimpleName(FileObject fo) {
|
||||
URI uri = fo.toUri();
|
||||
String s = uri.getSchemeSpecificPart();
|
||||
return s.substring(s.lastIndexOf("/") + 1); // safe when / not found
|
||||
|
||||
}
|
||||
|
||||
// force subtypes to define equals
|
||||
@Override
|
||||
public abstract boolean equals(Object other);
|
||||
|
||||
// force subtypes to define hashCode
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
/** The file manager that created this JavaFileObject. */
|
||||
protected final JavacFileManager fileManager;
|
||||
}
|
||||
@ -48,7 +48,7 @@ public class FSInfo {
|
||||
try {
|
||||
return file.toRealPath();
|
||||
} catch (IOException e) {
|
||||
return file.toAbsolutePath();
|
||||
return file.toAbsolutePath().normalize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -200,7 +200,7 @@ public class JRTIndex {
|
||||
if (Files.exists(dir)) {
|
||||
try (DirectoryStream<Path> modules = Files.newDirectoryStream(dir)) {
|
||||
for (Path module: modules) {
|
||||
Path p = rd.getFile(module);
|
||||
Path p = rd.resolveAgainst(module);
|
||||
if (!Files.exists(p))
|
||||
continue;
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(p)) {
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
package com.sun.tools.javac.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
@ -34,16 +33,20 @@ import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.FileVisitOption;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
@ -53,7 +56,6 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.tools.FileObject;
|
||||
@ -69,6 +71,8 @@ import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
|
||||
import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
|
||||
|
||||
import static javax.tools.StandardLocation.*;
|
||||
|
||||
/**
|
||||
@ -92,9 +96,6 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
|
||||
private FSInfo fsInfo;
|
||||
|
||||
private boolean contextUseOptimizedZip;
|
||||
private ZipFileIndexCache zipFileIndexCache;
|
||||
|
||||
private final Set<JavaFileObject.Kind> sourceOrClass =
|
||||
EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
|
||||
|
||||
@ -149,10 +150,6 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
|
||||
fsInfo = FSInfo.instance(context);
|
||||
|
||||
contextUseOptimizedZip = options.getBoolean("useOptimizedZip", true);
|
||||
if (contextUseOptimizedZip)
|
||||
zipFileIndexCache = ZipFileIndexCache.getSharedInstance();
|
||||
|
||||
symbolFileEnabled = !options.isSet("ignore.symbol.file");
|
||||
|
||||
String sf = options.get("sortFiles");
|
||||
@ -173,13 +170,13 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
}
|
||||
|
||||
// used by tests
|
||||
public JavaFileObject getFileForInput(String name) {
|
||||
return getRegularFile(Paths.get(name));
|
||||
public JavaFileObject getJavaFileObject(String name) {
|
||||
return getJavaFileObjects(name).iterator().next();
|
||||
}
|
||||
|
||||
// used by tests
|
||||
public JavaFileObject getRegularFile(Path file) {
|
||||
return new RegularFileObject(this, file);
|
||||
public JavaFileObject getJavaFileObject(Path file) {
|
||||
return getJavaFileObjects(file).iterator().next();
|
||||
}
|
||||
|
||||
public JavaFileObject getFileForOutput(String classname,
|
||||
@ -277,7 +274,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
for (Path file: e.files.values()) {
|
||||
if (fileKinds.contains(getKind(file))) {
|
||||
JavaFileObject fe
|
||||
= PathFileObject.createJRTPathFileObject(JavacFileManager.this, file);
|
||||
= PathFileObject.forJRTPath(JavacFileManager.this, file);
|
||||
resultList.append(fe);
|
||||
}
|
||||
}
|
||||
@ -302,14 +299,14 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
* Insert all files in subdirectory subdirectory of directory directory
|
||||
* which match fileKinds into resultList
|
||||
*/
|
||||
private void listDirectory(Path directory,
|
||||
private void listDirectory(Path directory, Path realDirectory,
|
||||
RelativeDirectory subdirectory,
|
||||
Set<JavaFileObject.Kind> fileKinds,
|
||||
boolean recurse,
|
||||
ListBuffer<JavaFileObject> resultList) {
|
||||
Path d;
|
||||
try {
|
||||
d = subdirectory.getFile(directory);
|
||||
d = subdirectory.resolveAgainst(directory);
|
||||
} catch (InvalidPathException ignore) {
|
||||
return;
|
||||
}
|
||||
@ -329,13 +326,16 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
return;
|
||||
}
|
||||
|
||||
if (realDirectory == null)
|
||||
realDirectory = fsInfo.getCanonicalFile(directory);
|
||||
|
||||
for (Path f: files) {
|
||||
String fname = f.getFileName().toString();
|
||||
if (fname.endsWith("/"))
|
||||
fname = fname.substring(0, fname.length() - 1);
|
||||
if (Files.isDirectory(f)) {
|
||||
if (recurse && SourceVersion.isIdentifier(fname)) {
|
||||
listDirectory(directory,
|
||||
listDirectory(directory, realDirectory,
|
||||
new RelativeDirectory(subdirectory, fname),
|
||||
fileKinds,
|
||||
recurse,
|
||||
@ -343,8 +343,9 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
}
|
||||
} else {
|
||||
if (isValidFile(fname, fileKinds)) {
|
||||
JavaFileObject fe =
|
||||
new RegularFileObject(this, fname, d.resolve(fname));
|
||||
RelativeFile file = new RelativeFile(subdirectory, fname);
|
||||
JavaFileObject fe = PathFileObject.forDirectoryPath(this,
|
||||
file.resolveAgainst(realDirectory), directory, file);
|
||||
resultList.append(fe);
|
||||
}
|
||||
}
|
||||
@ -352,34 +353,61 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert all files in subdirectory subdirectory of archive archive
|
||||
* Insert all files in subdirectory subdirectory of archive archivePath
|
||||
* which match fileKinds into resultList
|
||||
*/
|
||||
private void listArchive(Archive archive,
|
||||
RelativeDirectory subdirectory,
|
||||
Set<JavaFileObject.Kind> fileKinds,
|
||||
boolean recurse,
|
||||
ListBuffer<JavaFileObject> resultList) {
|
||||
// Get the files directly in the subdir
|
||||
List<String> files = archive.getFiles(subdirectory);
|
||||
if (files != null) {
|
||||
for (; !files.isEmpty(); files = files.tail) {
|
||||
String file = files.head;
|
||||
if (isValidFile(file, fileKinds)) {
|
||||
resultList.append(archive.getFileObject(subdirectory, file));
|
||||
}
|
||||
}
|
||||
private void listArchive(Path archivePath,
|
||||
RelativeDirectory subdirectory,
|
||||
Set<JavaFileObject.Kind> fileKinds,
|
||||
boolean recurse,
|
||||
ListBuffer<JavaFileObject> resultList)
|
||||
throws IOException {
|
||||
FileSystem fs = getFileSystem(archivePath);
|
||||
if (fs == null) {
|
||||
return;
|
||||
}
|
||||
if (recurse) {
|
||||
for (RelativeDirectory s: archive.getSubdirectories()) {
|
||||
if (subdirectory.contains(s)) {
|
||||
// Because the archive map is a flat list of directories,
|
||||
// the enclosing loop will pick up all child subdirectories.
|
||||
// Therefore, there is no need to recurse deeper.
|
||||
listArchive(archive, s, fileKinds, false, resultList);
|
||||
}
|
||||
}
|
||||
|
||||
Path containerSubdir = subdirectory.resolveAgainst(fs);
|
||||
if (!Files.exists(containerSubdir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int maxDepth = (recurse ? Integer.MAX_VALUE : 1);
|
||||
Set<FileVisitOption> opts = EnumSet.of(FOLLOW_LINKS);
|
||||
Files.walkFileTree(containerSubdir, opts, maxDepth,
|
||||
new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
|
||||
if (isValid(dir.getFileName())) {
|
||||
return FileVisitResult.CONTINUE;
|
||||
} else {
|
||||
return FileVisitResult.SKIP_SUBTREE;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isValid(Path fileName) {
|
||||
if (fileName == null) {
|
||||
return true;
|
||||
} else {
|
||||
String name = fileName.toString();
|
||||
if (name.endsWith("/")) {
|
||||
name = name.substring(0, name.length() - 1);
|
||||
}
|
||||
return SourceVersion.isIdentifier(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||
if (attrs.isRegularFile() && fileKinds.contains(getKind(file.getFileName().toString()))) {
|
||||
JavaFileObject fe = PathFileObject.forJarPath(
|
||||
JavacFileManager.this, file, archivePath);
|
||||
resultList.append(fe);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -391,54 +419,46 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
RelativeDirectory subdirectory,
|
||||
Set<JavaFileObject.Kind> fileKinds,
|
||||
boolean recurse,
|
||||
ListBuffer<JavaFileObject> resultList) {
|
||||
Archive archive = archives.get(container);
|
||||
if (archive == null) {
|
||||
// Very temporary and obnoxious interim hack
|
||||
if (container.endsWith("bootmodules.jimage")) {
|
||||
System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:");
|
||||
container = Locations.JRT_MARKER_FILE;
|
||||
} else if (container.getFileName().toString().endsWith(".jimage")) {
|
||||
System.err.println("Warning: reference to " + container + " ignored");
|
||||
return;
|
||||
}
|
||||
|
||||
// archives are not created for directories or jrt: images
|
||||
if (container == Locations.JRT_MARKER_FILE) {
|
||||
try {
|
||||
listJRTImage(subdirectory,
|
||||
fileKinds,
|
||||
recurse,
|
||||
resultList);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace(System.err);
|
||||
log.error("error.reading.file", container, getMessage(ex));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsInfo.isDirectory(container)) {
|
||||
listDirectory(container,
|
||||
subdirectory,
|
||||
fileKinds,
|
||||
recurse,
|
||||
resultList);
|
||||
return;
|
||||
}
|
||||
|
||||
// Not a directory; either a file or non-existant, create the archive
|
||||
try {
|
||||
archive = openArchive(container);
|
||||
} catch (IOException ex) {
|
||||
log.error("error.reading.file", container, getMessage(ex));
|
||||
return;
|
||||
}
|
||||
ListBuffer<JavaFileObject> resultList)
|
||||
throws IOException {
|
||||
// Very temporary and obnoxious interim hack
|
||||
if (container.endsWith("bootmodules.jimage")) {
|
||||
System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:");
|
||||
container = Locations.JRT_MARKER_FILE;
|
||||
} else if (container.getFileName().toString().endsWith(".jimage")) {
|
||||
System.err.println("Warning: reference to " + container + " ignored");
|
||||
return;
|
||||
}
|
||||
listArchive(archive,
|
||||
|
||||
if (container == Locations.JRT_MARKER_FILE) {
|
||||
try {
|
||||
listJRTImage(subdirectory,
|
||||
fileKinds,
|
||||
recurse,
|
||||
resultList);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace(System.err);
|
||||
log.error("error.reading.file", container, getMessage(ex));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsInfo.isDirectory(container)) {
|
||||
listDirectory(container, null,
|
||||
subdirectory,
|
||||
fileKinds,
|
||||
recurse,
|
||||
resultList);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Files.exists(container)) {
|
||||
listArchive(container,
|
||||
subdirectory,
|
||||
fileKinds,
|
||||
recurse,
|
||||
resultList);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
|
||||
@ -481,141 +501,17 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
return j < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* An archive provides a flat directory structure of a ZipFile by
|
||||
* mapping directory names to lists of files (basenames).
|
||||
*/
|
||||
public interface Archive {
|
||||
void close() throws IOException;
|
||||
|
||||
boolean contains(RelativePath name);
|
||||
|
||||
JavaFileObject getFileObject(RelativeDirectory subdirectory, String file);
|
||||
|
||||
List<String> getFiles(RelativeDirectory subdirectory);
|
||||
|
||||
Set<RelativeDirectory> getSubdirectories();
|
||||
private FileSystem getFileSystem(Path path) throws IOException {
|
||||
Path realPath = fsInfo.getCanonicalFile(path);
|
||||
FileSystem fs = fileSystems.get(realPath);
|
||||
if (fs == null) {
|
||||
fileSystems.put(realPath, fs = FileSystems.newFileSystem(realPath, null));
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
|
||||
public class MissingArchive implements Archive {
|
||||
final Path zipFileName;
|
||||
public MissingArchive(Path name) {
|
||||
zipFileName = name;
|
||||
}
|
||||
@Override
|
||||
public boolean contains(RelativePath name) {
|
||||
return false;
|
||||
}
|
||||
private final Map<Path,FileSystem> fileSystems = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getFiles(RelativeDirectory subdirectory) {
|
||||
return List.nil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RelativeDirectory> getSubdirectories() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MissingArchive[" + zipFileName + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/** A directory of zip files already opened.
|
||||
*/
|
||||
Map<Path, Archive> archives = new HashMap<>();
|
||||
|
||||
/*
|
||||
* This method looks for a ZipFormatException and takes appropriate
|
||||
* evasive action. If there is a failure in the fast mode then we
|
||||
* fail over to the platform zip, and allow it to deal with a potentially
|
||||
* non compliant zip file.
|
||||
*/
|
||||
protected Archive openArchive(Path zipFilename) throws IOException {
|
||||
try {
|
||||
return openArchive(zipFilename, contextUseOptimizedZip);
|
||||
} catch (IOException ioe) {
|
||||
if (ioe instanceof ZipFileIndex.ZipFormatException) {
|
||||
return openArchive(zipFilename, false);
|
||||
} else {
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Open a new zip file directory, and cache it.
|
||||
*/
|
||||
private Archive openArchive(Path zipFileName, boolean useOptimizedZip) throws IOException {
|
||||
Archive archive;
|
||||
try {
|
||||
|
||||
ZipFile zdir = null;
|
||||
|
||||
boolean usePreindexedCache = false;
|
||||
String preindexCacheLocation = null;
|
||||
|
||||
if (!useOptimizedZip) {
|
||||
zdir = new ZipFile(zipFileName.toFile());
|
||||
} else {
|
||||
usePreindexedCache = options.isSet("usezipindex");
|
||||
preindexCacheLocation = options.get("java.io.tmpdir");
|
||||
String optCacheLoc = options.get("cachezipindexdir");
|
||||
|
||||
if (optCacheLoc != null && optCacheLoc.length() != 0) {
|
||||
if (optCacheLoc.startsWith("\"")) {
|
||||
if (optCacheLoc.endsWith("\"")) {
|
||||
optCacheLoc = optCacheLoc.substring(1, optCacheLoc.length() - 1);
|
||||
}
|
||||
else {
|
||||
optCacheLoc = optCacheLoc.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
File cacheDir = new File(optCacheLoc);
|
||||
if (cacheDir.exists() && cacheDir.canWrite()) {
|
||||
preindexCacheLocation = optCacheLoc;
|
||||
if (!preindexCacheLocation.endsWith("/") &&
|
||||
!preindexCacheLocation.endsWith(File.separator)) {
|
||||
preindexCacheLocation += File.separator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!useOptimizedZip) {
|
||||
archive = new ZipArchive(this, zdir);
|
||||
} else {
|
||||
archive = new ZipFileIndexArchive(this,
|
||||
zipFileIndexCache.getZipFileIndex(zipFileName,
|
||||
null,
|
||||
usePreindexedCache,
|
||||
preindexCacheLocation,
|
||||
options.isSet("writezipindexfiles")));
|
||||
}
|
||||
} catch (FileNotFoundException | NoSuchFileException ex) {
|
||||
archive = new MissingArchive(zipFileName);
|
||||
} catch (ZipFileIndex.ZipFormatException zfe) {
|
||||
throw zfe;
|
||||
} catch (IOException ex) {
|
||||
if (Files.exists(zipFileName))
|
||||
log.error("error.reading.file", zipFileName, getMessage(ex));
|
||||
archive = new MissingArchive(zipFileName);
|
||||
}
|
||||
|
||||
archives.put(zipFileName, archive);
|
||||
return archive;
|
||||
}
|
||||
|
||||
/** Flush any output resources.
|
||||
*/
|
||||
@ -628,15 +524,9 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
* Close the JavaFileManager, releasing resources.
|
||||
*/
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public void close() {
|
||||
for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) {
|
||||
Archive a = i.next();
|
||||
i.remove();
|
||||
try {
|
||||
a.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
public void close() throws IOException {
|
||||
for (FileSystem fs: fileSystems.values())
|
||||
fs.close();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
@ -689,10 +579,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
return null;
|
||||
}
|
||||
|
||||
if (file instanceof BaseFileObject) {
|
||||
return ((BaseFileObject) file).inferBinaryName(path);
|
||||
} else if (file instanceof PathFileObject) {
|
||||
return ((PathFileObject) file).inferBinaryName(null);
|
||||
if (file instanceof PathFileObject) {
|
||||
return ((PathFileObject) file).inferBinaryName(path);
|
||||
} else
|
||||
throw new IllegalArgumentException(file.getClass().getName());
|
||||
}
|
||||
@ -703,11 +591,6 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
nullCheck(b);
|
||||
if (a instanceof PathFileObject && b instanceof PathFileObject)
|
||||
return ((PathFileObject) a).isSameFile((PathFileObject) b);
|
||||
// In time, we should phase out BaseFileObject in favor of PathFileObject
|
||||
if (!(a instanceof BaseFileObject || a instanceof PathFileObject))
|
||||
throw new IllegalArgumentException("Not supported: " + a);
|
||||
if (!(b instanceof BaseFileObject || b instanceof PathFileObject))
|
||||
throw new IllegalArgumentException("Not supported: " + b);
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
@ -754,32 +637,29 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
return null;
|
||||
|
||||
for (Path file: path) {
|
||||
Archive a = archives.get(file);
|
||||
if (a == null) {
|
||||
// archives are not created for directories or jrt: images
|
||||
if (file == Locations.JRT_MARKER_FILE) {
|
||||
JRTIndex.Entry e = getJRTIndex().getEntry(name.dirname());
|
||||
if (symbolFileEnabled && e.ctSym.hidden)
|
||||
continue;
|
||||
Path p = e.files.get(name.basename());
|
||||
if (p != null)
|
||||
return PathFileObject.createJRTPathFileObject(this, p);
|
||||
continue;
|
||||
} else if (fsInfo.isDirectory(file)) {
|
||||
try {
|
||||
Path f = name.getFile(file);
|
||||
if (Files.exists(f))
|
||||
return new RegularFileObject(this, f);
|
||||
} catch (InvalidPathException ignore) {
|
||||
}
|
||||
if (file == Locations.JRT_MARKER_FILE) {
|
||||
JRTIndex.Entry e = getJRTIndex().getEntry(name.dirname());
|
||||
if (symbolFileEnabled && e.ctSym.hidden)
|
||||
continue;
|
||||
Path p = e.files.get(name.basename());
|
||||
if (p != null)
|
||||
return PathFileObject.forJRTPath(this, p);
|
||||
} else if (fsInfo.isDirectory(file)) {
|
||||
try {
|
||||
Path f = name.resolveAgainst(file);
|
||||
if (Files.exists(f))
|
||||
return PathFileObject.forSimplePath(this,
|
||||
fsInfo.getCanonicalFile(f), f);
|
||||
} catch (InvalidPathException ignore) {
|
||||
}
|
||||
} else if (Files.exists(file)) {
|
||||
FileSystem fs = getFileSystem(file);
|
||||
if (fs != null) {
|
||||
Path fsRoot = fs.getRootDirectories().iterator().next();
|
||||
Path f = name.resolveAgainst(fsRoot);
|
||||
if (Files.exists(f))
|
||||
return PathFileObject.forJarPath(this, f, file);
|
||||
}
|
||||
// Not a directory, create the archive
|
||||
a = openArchive(file);
|
||||
}
|
||||
// Process the archive
|
||||
if (a.contains(name)) {
|
||||
return a.getFileObject(name.dirname(), name.basename());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -829,14 +709,14 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
if (getClassOutDir() != null) {
|
||||
dir = getClassOutDir();
|
||||
} else {
|
||||
Path siblingDir = null;
|
||||
if (sibling != null && sibling instanceof RegularFileObject) {
|
||||
siblingDir = ((RegularFileObject)sibling).file.getParent();
|
||||
String baseName = fileName.basename();
|
||||
if (sibling != null && sibling instanceof PathFileObject) {
|
||||
return ((PathFileObject) sibling).getSibling(baseName);
|
||||
} else {
|
||||
Path p = Paths.get(baseName);
|
||||
Path real = fsInfo.getCanonicalFile(p);
|
||||
return PathFileObject.forSimplePath(this, real, p);
|
||||
}
|
||||
if (siblingDir == null)
|
||||
return new RegularFileObject(this, Paths.get(fileName.basename()));
|
||||
else
|
||||
return new RegularFileObject(this, siblingDir.resolve(fileName.basename()));
|
||||
}
|
||||
} else if (location == SOURCE_OUTPUT) {
|
||||
dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
|
||||
@ -850,8 +730,11 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
}
|
||||
|
||||
try {
|
||||
Path file = fileName.getFile(dir); // null-safe
|
||||
return new RegularFileObject(this, file);
|
||||
if (dir == null) {
|
||||
dir = Paths.get(System.getProperty("user.dir"));
|
||||
}
|
||||
Path path = fileName.resolveAgainst(fsInfo.getCanonicalFile(dir));
|
||||
return PathFileObject.forDirectoryPath(this, path, dir, fileName);
|
||||
} catch (InvalidPathException e) {
|
||||
throw new IOException("bad filename " + fileName, e);
|
||||
}
|
||||
@ -861,13 +744,17 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
|
||||
Iterable<? extends File> files)
|
||||
{
|
||||
ArrayList<RegularFileObject> result;
|
||||
ArrayList<PathFileObject> result;
|
||||
if (files instanceof Collection<?>)
|
||||
result = new ArrayList<>(((Collection<?>)files).size());
|
||||
else
|
||||
result = new ArrayList<>();
|
||||
for (File f: files)
|
||||
result.add(new RegularFileObject(this, nullCheck(f).toPath()));
|
||||
for (File f: files) {
|
||||
Objects.requireNonNull(f);
|
||||
Path p = f.toPath();
|
||||
result.add(PathFileObject.forSimplePath(this,
|
||||
fsInfo.getCanonicalFile(p), p));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -875,13 +762,14 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
|
||||
Iterable<? extends Path> paths)
|
||||
{
|
||||
ArrayList<RegularFileObject> result;
|
||||
ArrayList<PathFileObject> result;
|
||||
if (paths instanceof Collection<?>)
|
||||
result = new ArrayList<>(((Collection<?>)paths).size());
|
||||
else
|
||||
result = new ArrayList<>();
|
||||
for (Path p: paths)
|
||||
result.add(new RegularFileObject(this, nullCheck(p)));
|
||||
result.add(PathFileObject.forSimplePath(this,
|
||||
fsInfo.getCanonicalFile(p), p));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -935,8 +823,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public Path asPath(FileObject file) {
|
||||
if (file instanceof RegularFileObject) {
|
||||
return ((RegularFileObject) file).file;
|
||||
if (file instanceof PathFileObject) {
|
||||
return ((PathFileObject) file).path;
|
||||
} else
|
||||
throw new IllegalArgumentException(file.getName());
|
||||
}
|
||||
|
||||
@ -33,18 +33,24 @@ import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.Path;
|
||||
import java.text.Normalizer;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.NestingKind;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeFile;
|
||||
import com.sun.tools.javac.util.DefinedBy;
|
||||
import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
|
||||
@ -53,10 +59,16 @@ import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
* Implementation of JavaFileObject using java.nio.file API.
|
||||
*
|
||||
* <p>PathFileObjects are, for the most part, straightforward wrappers around
|
||||
* Path objects. The primary complexity is the support for "inferBinaryName".
|
||||
* This is left as an abstract method, implemented by each of a number of
|
||||
* different factory methods, which compute the binary name based on
|
||||
* information available at the time the file object is created.
|
||||
* immutable absolute Path objects. Different subtypes are used to provide
|
||||
* specialized implementations of "inferBinaryName" and "getName" that capture
|
||||
* additional information available at the time the object is created.
|
||||
*
|
||||
* <p>In general, {@link JavaFileManager#isSameFile} should be used to
|
||||
* determine whether two file objects refer to the same file on disk.
|
||||
* PathFileObject also supports the standard {@code equals} and {@code hashCode}
|
||||
* methods, primarily for convenience when working with collections.
|
||||
* All of these operations delegate to the equivalent operations on the
|
||||
* underlying Path object.
|
||||
*
|
||||
* <p><b>This is NOT part of any supported API.
|
||||
* If you write code that depends on this, you do so at your own risk.
|
||||
@ -64,108 +76,297 @@ import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public abstract class PathFileObject implements JavaFileObject {
|
||||
private final BaseFileManager fileManager;
|
||||
private final Path path;
|
||||
private static final FileSystem defaultFileSystem = FileSystems.getDefault();
|
||||
private static final boolean isMacOS = System.getProperty("os.name", "").contains("OS X");
|
||||
|
||||
protected final BaseFileManager fileManager;
|
||||
protected final Path path;
|
||||
private boolean hasParents;
|
||||
|
||||
/**
|
||||
* Create a PathFileObject within a directory, such that the binary name
|
||||
* can be inferred from the relationship to the parent directory.
|
||||
* Create a PathFileObject for a file within a directory, such that the
|
||||
* binary name can be inferred from the relationship to an enclosing directory.
|
||||
*
|
||||
* The binary name is derived from {@code relativePath}.
|
||||
* The name is derived from the composition of {@code userPackageRootDir}
|
||||
* and {@code relativePath}.
|
||||
*
|
||||
* @param fileManager the file manager creating this file object
|
||||
* @param path the absolute path referred to by this file object
|
||||
* @param userPackageRootDir the path of the directory containing the
|
||||
* root of the package hierarchy
|
||||
* @param relativePath the path of this file relative to {@code userPackageRootDir}
|
||||
*/
|
||||
static PathFileObject createDirectoryPathFileObject(BaseFileManager fileManager,
|
||||
final Path path, final Path dir) {
|
||||
return new PathFileObject(fileManager, path) {
|
||||
@Override
|
||||
public String inferBinaryName(Iterable<? extends Path> paths) {
|
||||
return toBinaryName(dir.relativize(path));
|
||||
}
|
||||
};
|
||||
static PathFileObject forDirectoryPath(BaseFileManager fileManager, Path path,
|
||||
Path userPackageRootDir, RelativePath relativePath) {
|
||||
return new DirectoryFileObject(fileManager, path, userPackageRootDir, relativePath);
|
||||
}
|
||||
|
||||
private static class DirectoryFileObject extends PathFileObject {
|
||||
private final Path userPackageRootDir;
|
||||
private final RelativePath relativePath;
|
||||
|
||||
private DirectoryFileObject(BaseFileManager fileManager, Path path,
|
||||
Path userPackageRootDir, RelativePath relativePath) {
|
||||
super(fileManager, path);
|
||||
this.userPackageRootDir = userPackageRootDir;
|
||||
this.relativePath = relativePath;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public String getName() {
|
||||
return relativePath.resolveAgainst(userPackageRootDir).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String inferBinaryName(Iterable<? extends Path> paths) {
|
||||
return toBinaryName(relativePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DirectoryFileObject[" + userPackageRootDir + ":" + relativePath.path + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
PathFileObject getSibling(String baseName) {
|
||||
return new DirectoryFileObject(fileManager,
|
||||
path.resolveSibling(baseName),
|
||||
userPackageRootDir,
|
||||
new RelativeFile(relativePath.dirname(), baseName)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PathFileObject in a file system such as a jar file, such that
|
||||
* the binary name can be inferred from its position within the filesystem.
|
||||
* Create a PathFileObject for a file in a file system such as a jar file,
|
||||
* such that the binary name can be inferred from its position within the
|
||||
* file system.
|
||||
*
|
||||
* The binary name is derived from {@code path}.
|
||||
* The name is derived from the composition of {@code userJarPath}
|
||||
* and {@code path}.
|
||||
*
|
||||
* @param fileManager the file manager creating this file object
|
||||
* @param path the path referred to by this file object
|
||||
* @param userJarPath the path of the jar file containing the file system.
|
||||
*/
|
||||
public static PathFileObject createJarPathFileObject(BaseFileManager fileManager,
|
||||
public static PathFileObject forJarPath(BaseFileManager fileManager,
|
||||
Path path, Path userJarPath) {
|
||||
return new JarFileObject(fileManager, path, userJarPath);
|
||||
}
|
||||
|
||||
private static class JarFileObject extends PathFileObject {
|
||||
private final Path userJarPath;
|
||||
|
||||
private JarFileObject(BaseFileManager fileManager, Path path, Path userJarPath) {
|
||||
super(fileManager, path);
|
||||
this.userJarPath = userJarPath;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public String getName() {
|
||||
// The use of ( ) to delimit the entry name is not ideal
|
||||
// but it does match earlier behavior
|
||||
return userJarPath + "(" + path + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String inferBinaryName(Iterable<? extends Path> paths) {
|
||||
Path root = path.getFileSystem().getRootDirectories().iterator().next();
|
||||
return toBinaryName(root.relativize(path));
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public URI toUri() {
|
||||
// Work around bug JDK-8134451:
|
||||
// path.toUri() returns double-encoded URIs, that cannot be opened by URLConnection
|
||||
return createJarUri(userJarPath, path.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JarFileObject[" + userJarPath + ":" + path + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
PathFileObject getSibling(String baseName) {
|
||||
return new JarFileObject(fileManager,
|
||||
path.resolveSibling(baseName),
|
||||
userJarPath
|
||||
);
|
||||
}
|
||||
|
||||
private static URI createJarUri(Path jarFile, String entryName) {
|
||||
URI jarURI = jarFile.toUri().normalize();
|
||||
String separator = entryName.startsWith("/") ? "!" : "!/";
|
||||
try {
|
||||
// The jar URI convention appears to be not to re-encode the jarURI
|
||||
return new URI("jar:" + jarURI + separator + entryName);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new CannotCreateUriError(jarURI + separator + entryName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PathFileObject for a file in a modular file system, such as jrt:,
|
||||
* such that the binary name can be inferred from its position within the
|
||||
* filesystem.
|
||||
*
|
||||
* The binary name is derived from {@code path}, ignoring the first two
|
||||
* elements of the name (which are "modules" and a module name).
|
||||
* The name is derived from {@code path}.
|
||||
*
|
||||
* @param fileManager the file manager creating this file object
|
||||
* @param path the path referred to by this file object
|
||||
*/
|
||||
public static PathFileObject forJRTPath(BaseFileManager fileManager,
|
||||
final Path path) {
|
||||
return new PathFileObject(fileManager, path) {
|
||||
@Override
|
||||
public String inferBinaryName(Iterable<? extends Path> paths) {
|
||||
return toBinaryName(path);
|
||||
}
|
||||
};
|
||||
return new JRTFileObject(fileManager, path);
|
||||
}
|
||||
|
||||
private static class JRTFileObject extends PathFileObject {
|
||||
// private final Path javaHome;
|
||||
private JRTFileObject(BaseFileManager fileManager, Path path) {
|
||||
super(fileManager, path);
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public String getName() {
|
||||
return path.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String inferBinaryName(Iterable<? extends Path> paths) {
|
||||
// use subpath to ignore the leading /modules/MODULE-NAME
|
||||
return toBinaryName(path.subpath(2, path.getNameCount()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JRTFileObject[" + path + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
PathFileObject getSibling(String baseName) {
|
||||
return new JRTFileObject(fileManager,
|
||||
path.resolveSibling(baseName)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PathFileObject in a modular file system, such as jrt:, such that
|
||||
* the binary name can be inferred from its position within the filesystem.
|
||||
* Create a PathFileObject for a file whose binary name must be inferred
|
||||
* from its position on a search path.
|
||||
*
|
||||
* The binary name is inferred by finding an enclosing directory in
|
||||
* the sequence of paths associated with the location given to
|
||||
* {@link JavaFileManager#inferBinaryName).
|
||||
* The name is derived from {@code userPath}.
|
||||
*
|
||||
* @param fileManager the file manager creating this file object
|
||||
* @param path the path referred to by this file object
|
||||
* @param userPath the "user-friendly" name for this path.
|
||||
*/
|
||||
public static PathFileObject createJRTPathFileObject(BaseFileManager fileManager,
|
||||
final Path path) {
|
||||
return new PathFileObject(fileManager, path) {
|
||||
@Override
|
||||
public String inferBinaryName(Iterable<? extends Path> paths) {
|
||||
// use subpath to ignore the leading /modules/MODULE-NAME
|
||||
return toBinaryName(path.subpath(2, path.getNameCount()));
|
||||
}
|
||||
};
|
||||
static PathFileObject forSimplePath(BaseFileManager fileManager,
|
||||
Path path, Path userPath) {
|
||||
return new SimpleFileObject(fileManager, path, userPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PathFileObject whose binary name can be inferred from the
|
||||
* relative path to a sibling.
|
||||
*/
|
||||
static PathFileObject createSiblingPathFileObject(BaseFileManager fileManager,
|
||||
final Path path, final String relativePath) {
|
||||
return new PathFileObject(fileManager, path) {
|
||||
@Override
|
||||
public String inferBinaryName(Iterable<? extends Path> paths) {
|
||||
return toBinaryName(relativePath, "/");
|
||||
}
|
||||
};
|
||||
}
|
||||
private static class SimpleFileObject extends PathFileObject {
|
||||
private final Path userPath;
|
||||
private SimpleFileObject(BaseFileManager fileManager, Path path, Path userPath) {
|
||||
super(fileManager, path);
|
||||
this.userPath = userPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PathFileObject whose binary name might be inferred from its
|
||||
* position on a search path.
|
||||
*/
|
||||
static PathFileObject createSimplePathFileObject(BaseFileManager fileManager,
|
||||
final Path path) {
|
||||
return new PathFileObject(fileManager, path) {
|
||||
@Override
|
||||
public String inferBinaryName(Iterable<? extends Path> paths) {
|
||||
Path absPath = path.toAbsolutePath();
|
||||
for (Path p: paths) {
|
||||
Path ap = p.toAbsolutePath();
|
||||
if (absPath.startsWith(ap)) {
|
||||
try {
|
||||
Path rp = ap.relativize(absPath);
|
||||
if (rp != null) // maybe null if absPath same as ap
|
||||
return toBinaryName(rp);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// ignore this p if cannot relativize path to p
|
||||
}
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public String getName() {
|
||||
return userPath.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String inferBinaryName(Iterable<? extends Path> paths) {
|
||||
Path absPath = path.toAbsolutePath();
|
||||
for (Path p: paths) {
|
||||
Path ap = p.toAbsolutePath();
|
||||
if (absPath.startsWith(ap)) {
|
||||
try {
|
||||
Path rp = ap.relativize(absPath);
|
||||
if (rp != null) // maybe null if absPath same as ap
|
||||
return toBinaryName(rp);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// ignore this p if cannot relativize path to p
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
PathFileObject getSibling(String baseName) {
|
||||
return new SimpleFileObject(fileManager,
|
||||
path.resolveSibling(baseName),
|
||||
userPath.resolveSibling(baseName)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PathFileObject, for a specified path, in the context of
|
||||
* a given file manager.
|
||||
*
|
||||
* In general, this path should be an
|
||||
* {@link Path#toAbsolutePath absolute path}, if not a
|
||||
* {@link Path#toRealPath} real path.
|
||||
* It will be used as the basis of {@code equals}, {@code hashCode}
|
||||
* and {@code isSameFile} methods on this file object.
|
||||
*
|
||||
* A PathFileObject should also have a "friendly name" per the
|
||||
* specification for {@link FileObject#getName}. The friendly name
|
||||
* is provided by the various subtypes of {@code PathFileObject}.
|
||||
*
|
||||
* @param fileManager the file manager creating this file object
|
||||
* @param path the path contained in this file object.
|
||||
*/
|
||||
protected PathFileObject(BaseFileManager fileManager, Path path) {
|
||||
this.fileManager = Objects.requireNonNull(fileManager);
|
||||
this.path = Objects.requireNonNull(path);
|
||||
if (Files.isDirectory(path)) {
|
||||
throw new IllegalArgumentException("directories not supported");
|
||||
}
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public abstract String inferBinaryName(Iterable<? extends Path> paths);
|
||||
/**
|
||||
* See {@link JavacFileManager#inferBinaryName}.
|
||||
*/
|
||||
abstract String inferBinaryName(Iterable<? extends Path> paths);
|
||||
|
||||
/**
|
||||
* Return the file object for a sibling file with a given file name.
|
||||
* See {@link JavacFileManager#getFileForOutput} and
|
||||
* {@link JavacFileManager#getJavaFileForOutput}.
|
||||
*/
|
||||
abstract PathFileObject getSibling(String basename);
|
||||
|
||||
/**
|
||||
* Return the Path for this object.
|
||||
* @return the Path for this object.
|
||||
* @see StandardJavaFileManager#asPath
|
||||
*/
|
||||
public Path getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* The short name is used when generating raw diagnostics.
|
||||
* @return the last component of the path
|
||||
*/
|
||||
public String getShortName() {
|
||||
return path.getFileName().toString();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public Kind getKind() {
|
||||
return BaseFileManager.getKind(path.getFileName().toString());
|
||||
@ -174,22 +375,43 @@ public abstract class PathFileObject implements JavaFileObject {
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public boolean isNameCompatible(String simpleName, Kind kind) {
|
||||
Objects.requireNonNull(simpleName);
|
||||
// null check
|
||||
Objects.requireNonNull(kind);
|
||||
|
||||
if (kind == Kind.OTHER && getKind() != kind) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String sn = simpleName + kind.extension;
|
||||
String pn = path.getFileName().toString();
|
||||
if (pn.equals(sn)) {
|
||||
return true;
|
||||
}
|
||||
if (pn.equalsIgnoreCase(sn)) {
|
||||
try {
|
||||
// allow for Windows
|
||||
return path.toRealPath(LinkOption.NOFOLLOW_LINKS).getFileName().toString().equals(sn);
|
||||
} catch (IOException e) {
|
||||
|
||||
if (path.getFileSystem() == defaultFileSystem) {
|
||||
if (isMacOS) {
|
||||
String name = path.getFileName().toString();
|
||||
if (Normalizer.isNormalized(name, Normalizer.Form.NFD)
|
||||
&& Normalizer.isNormalized(sn, Normalizer.Form.NFC)) {
|
||||
// On Mac OS X it is quite possible to have the file name and the
|
||||
// given simple name normalized in different ways.
|
||||
// In that case we have to normalize file name to the
|
||||
// Normal Form Composed (NFC).
|
||||
String normName = Normalizer.normalize(name, Normalizer.Form.NFC);
|
||||
if (normName.equals(sn)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pn.equalsIgnoreCase(sn)) {
|
||||
try {
|
||||
// allow for Windows
|
||||
return path.toRealPath(LinkOption.NOFOLLOW_LINKS).getFileName().toString().equals(sn);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -208,11 +430,6 @@ public abstract class PathFileObject implements JavaFileObject {
|
||||
return path.toUri();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public String getName() {
|
||||
return path.toString();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public InputStream openInputStream() throws IOException {
|
||||
return Files.newInputStream(path);
|
||||
@ -264,7 +481,7 @@ public abstract class PathFileObject implements JavaFileObject {
|
||||
try {
|
||||
return Files.getLastModifiedTime(path).toMillis();
|
||||
} catch (IOException e) {
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,7 +495,7 @@ public abstract class PathFileObject implements JavaFileObject {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSameFile(PathFileObject other) {
|
||||
boolean isSameFile(PathFileObject other) {
|
||||
try {
|
||||
return Files.isSameFile(path, other.path);
|
||||
} catch (IOException e) {
|
||||
@ -302,17 +519,21 @@ public abstract class PathFileObject implements JavaFileObject {
|
||||
}
|
||||
|
||||
private void ensureParentDirectoriesExist() throws IOException {
|
||||
Path parent = path.getParent();
|
||||
if (parent != null)
|
||||
Files.createDirectories(parent);
|
||||
if (!hasParents) {
|
||||
Path parent = path.getParent();
|
||||
if (parent != null && !Files.isDirectory(parent)) {
|
||||
try {
|
||||
Files.createDirectories(parent);
|
||||
} catch (IOException e) {
|
||||
throw new IOException("could not create parent directories", e);
|
||||
}
|
||||
}
|
||||
hasParents = true;
|
||||
}
|
||||
}
|
||||
|
||||
private long size() {
|
||||
try {
|
||||
return Files.size(path);
|
||||
} catch (IOException e) {
|
||||
return -1;
|
||||
}
|
||||
protected static String toBinaryName(RelativePath relativePath) {
|
||||
return toBinaryName(relativePath.path, "/");
|
||||
}
|
||||
|
||||
protected static String toBinaryName(Path relativePath) {
|
||||
@ -320,12 +541,32 @@ public abstract class PathFileObject implements JavaFileObject {
|
||||
relativePath.getFileSystem().getSeparator());
|
||||
}
|
||||
|
||||
protected static String toBinaryName(String relativePath, String sep) {
|
||||
private static String toBinaryName(String relativePath, String sep) {
|
||||
return removeExtension(relativePath).replace(sep, ".");
|
||||
}
|
||||
|
||||
protected static String removeExtension(String fileName) {
|
||||
private static String removeExtension(String fileName) {
|
||||
int lastDot = fileName.lastIndexOf(".");
|
||||
return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
|
||||
}
|
||||
|
||||
/** Return the last component of a presumed hierarchical URI.
|
||||
* From the scheme specific part of the URI, it returns the substring
|
||||
* after the last "/" if any, or everything if no "/" is found.
|
||||
*/
|
||||
public static String getSimpleName(FileObject fo) {
|
||||
URI uri = fo.toUri();
|
||||
String s = uri.getSchemeSpecificPart();
|
||||
return s.substring(s.lastIndexOf("/") + 1); // safe when / not found
|
||||
|
||||
}
|
||||
|
||||
/** Used when URLSyntaxException is thrown unexpectedly during
|
||||
* implementations of FileObject.toURI(). */
|
||||
public static class CannotCreateUriError extends Error {
|
||||
private static final long serialVersionUID = 9101708840997613546L;
|
||||
public CannotCreateUriError(String value, Throwable cause) {
|
||||
super(value, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,265 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2014, 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.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.Normalizer;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.util.DefinedBy;
|
||||
import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
|
||||
/**
|
||||
* A subclass of JavaFileObject representing regular files.
|
||||
*
|
||||
* <p><b>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.</b>
|
||||
*/
|
||||
class RegularFileObject extends BaseFileObject {
|
||||
|
||||
/** Have the parent directories been created?
|
||||
*/
|
||||
private boolean hasParents = false;
|
||||
private String name;
|
||||
final Path file;
|
||||
private Reference<Path> absFileRef;
|
||||
final static boolean isMacOS = System.getProperty("os.name", "").contains("OS X");
|
||||
|
||||
public RegularFileObject(JavacFileManager fileManager, Path f) {
|
||||
this(fileManager, f.getFileName().toString(), f);
|
||||
}
|
||||
|
||||
public RegularFileObject(JavacFileManager fileManager, String name, Path f) {
|
||||
super(fileManager);
|
||||
if (Files.isDirectory(f)) {
|
||||
throw new IllegalArgumentException("directories not supported");
|
||||
}
|
||||
this.name = name;
|
||||
this.file = f;
|
||||
if (getLastModified() > System.currentTimeMillis())
|
||||
fileManager.log.warning("file.from.future", f);
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public URI toUri() {
|
||||
return file.toUri().normalize();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public String getName() {
|
||||
return file.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public JavaFileObject.Kind getKind() {
|
||||
return getKind(name);
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public InputStream openInputStream() throws IOException {
|
||||
return Files.newInputStream(file);
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
fileManager.flushCache(this);
|
||||
ensureParentDirectoriesExist();
|
||||
return Files.newOutputStream(file);
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||
CharBuffer cb = fileManager.getCachedContent(this);
|
||||
if (cb == null) {
|
||||
try (InputStream in = Files.newInputStream(file)) {
|
||||
ByteBuffer bb = fileManager.makeByteBuffer(in);
|
||||
JavaFileObject prev = fileManager.log.useSource(this);
|
||||
try {
|
||||
cb = fileManager.decode(bb, ignoreEncodingErrors);
|
||||
} finally {
|
||||
fileManager.log.useSource(prev);
|
||||
}
|
||||
fileManager.recycleByteBuffer(bb);
|
||||
if (!ignoreEncodingErrors) {
|
||||
fileManager.cache(this, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public Writer openWriter() throws IOException {
|
||||
fileManager.flushCache(this);
|
||||
ensureParentDirectoriesExist();
|
||||
return new OutputStreamWriter(Files.newOutputStream(file), fileManager.getEncodingName());
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public long getLastModified() {
|
||||
try {
|
||||
return Files.getLastModifiedTime(file).toMillis();
|
||||
} catch (IOException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public boolean delete() {
|
||||
try {
|
||||
Files.delete(file);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
|
||||
return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String inferBinaryName(Iterable<? extends Path> path) {
|
||||
String fPath = file.toString();
|
||||
//System.err.println("RegularFileObject " + file + " " +r.getPath());
|
||||
for (Path dir: path) {
|
||||
//System.err.println("dir: " + dir);
|
||||
String sep = dir.getFileSystem().getSeparator();
|
||||
String dPath = dir.toString();
|
||||
if (dPath.length() == 0)
|
||||
dPath = System.getProperty("user.dir");
|
||||
if (!dPath.endsWith(sep))
|
||||
dPath += sep;
|
||||
if (fPath.regionMatches(true, 0, dPath, 0, dPath.length())
|
||||
&& Paths.get(fPath.substring(0, dPath.length())).equals(Paths.get(dPath))) {
|
||||
String relativeName = fPath.substring(dPath.length());
|
||||
return removeExtension(relativeName).replace(sep, ".");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) {
|
||||
Objects.requireNonNull(cn);
|
||||
// null check
|
||||
if (kind == Kind.OTHER && getKind() != kind) {
|
||||
return false;
|
||||
}
|
||||
String n = cn + kind.extension;
|
||||
if (name.equals(n)) {
|
||||
return true;
|
||||
}
|
||||
if (isMacOS && Normalizer.isNormalized(name, Normalizer.Form.NFD)
|
||||
&& Normalizer.isNormalized(n, Normalizer.Form.NFC)) {
|
||||
// On Mac OS X it is quite possible to file name and class
|
||||
// name normalized in a different way - in that case we have to normalize file name
|
||||
// to the Normal Form Compised (NFC)
|
||||
String normName = Normalizer.normalize(name, Normalizer.Form.NFC);
|
||||
if (normName.equals(n)) {
|
||||
this.name = normName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (name.equalsIgnoreCase(n)) {
|
||||
try {
|
||||
// allow for Windows
|
||||
return file.toRealPath().getFileName().toString().equals(n);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ensureParentDirectoriesExist() throws IOException {
|
||||
if (!hasParents) {
|
||||
Path parent = file.getParent();
|
||||
if (parent != null && !Files.isDirectory(parent)) {
|
||||
try {
|
||||
Files.createDirectories(parent);
|
||||
} catch (IOException e) {
|
||||
throw new IOException("could not create parent directories", e);
|
||||
}
|
||||
}
|
||||
hasParents = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two file objects are equal.
|
||||
* Two RegularFileObjects are equal if the absolute paths of the underlying
|
||||
* files are equal.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other)
|
||||
return true;
|
||||
|
||||
if (!(other instanceof RegularFileObject))
|
||||
return false;
|
||||
|
||||
RegularFileObject o = (RegularFileObject) other;
|
||||
return getAbsoluteFile().equals(o.getAbsoluteFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getAbsoluteFile().hashCode();
|
||||
}
|
||||
|
||||
private Path getAbsoluteFile() {
|
||||
Path absFile = (absFileRef == null ? null : absFileRef.get());
|
||||
if (absFile == null) {
|
||||
absFile = file.toAbsolutePath();
|
||||
absFileRef = new SoftReference<>(absFile);
|
||||
}
|
||||
return absFile;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2015, 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
|
||||
@ -26,6 +26,7 @@
|
||||
package com.sun.tools.javac.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
@ -57,7 +58,7 @@ public abstract class RelativePath implements Comparable<RelativePath> {
|
||||
|
||||
public abstract String basename();
|
||||
|
||||
public Path getFile(Path directory) throws /*unchecked*/ InvalidPathException {
|
||||
public Path resolveAgainst(Path directory) throws /*unchecked*/ InvalidPathException {
|
||||
if (directory == null) {
|
||||
String sep = FileSystems.getDefault().getSeparator();
|
||||
return Paths.get(path.replace("/", sep));
|
||||
@ -67,6 +68,12 @@ public abstract class RelativePath implements Comparable<RelativePath> {
|
||||
}
|
||||
}
|
||||
|
||||
public Path resolveAgainst(FileSystem fs) throws /*unchecked*/ InvalidPathException {
|
||||
String sep = fs.getSeparator();
|
||||
Path root = fs.getRootDirectories().iterator().next();
|
||||
return root.resolve(path.replace("/", sep));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(RelativePath other) {
|
||||
return path.compareTo(other.path);
|
||||
|
||||
@ -1,290 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2015, 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.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.file.JavacFileManager.Archive;
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeFile;
|
||||
import com.sun.tools.javac.util.DefinedBy;
|
||||
import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
import com.sun.tools.javac.util.List;
|
||||
|
||||
/**
|
||||
* <p><b>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.</b>
|
||||
*/
|
||||
public class ZipArchive implements Archive {
|
||||
|
||||
public ZipArchive(JavacFileManager fm, ZipFile zfile) throws IOException {
|
||||
this(fm, zfile, true);
|
||||
}
|
||||
|
||||
protected ZipArchive(JavacFileManager fm, ZipFile zfile, boolean initMap) throws IOException {
|
||||
this.fileManager = fm;
|
||||
this.zfile = zfile;
|
||||
this.map = new HashMap<>();
|
||||
if (initMap)
|
||||
initMap();
|
||||
}
|
||||
|
||||
protected void initMap() throws IOException {
|
||||
for (Enumeration<? extends ZipEntry> e = zfile.entries(); e.hasMoreElements(); ) {
|
||||
ZipEntry entry;
|
||||
try {
|
||||
entry = e.nextElement();
|
||||
} catch (InternalError ex) {
|
||||
IOException io = new IOException();
|
||||
io.initCause(ex); // convenience constructors added in Mustang :-(
|
||||
throw io;
|
||||
}
|
||||
addZipEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void addZipEntry(ZipEntry entry) {
|
||||
String name = entry.getName();
|
||||
int i = name.lastIndexOf('/');
|
||||
RelativeDirectory dirname = new RelativeDirectory(name.substring(0, i+1));
|
||||
String basename = name.substring(i+1);
|
||||
if (basename.length() == 0)
|
||||
return;
|
||||
List<String> list = map.get(dirname);
|
||||
if (list == null)
|
||||
list = List.nil();
|
||||
list = list.prepend(basename);
|
||||
map.put(dirname, list);
|
||||
}
|
||||
|
||||
public boolean contains(RelativePath name) {
|
||||
RelativeDirectory dirname = name.dirname();
|
||||
String basename = name.basename();
|
||||
if (basename.length() == 0)
|
||||
return false;
|
||||
List<String> list = map.get(dirname);
|
||||
return (list != null && list.contains(basename));
|
||||
}
|
||||
|
||||
public List<String> getFiles(RelativeDirectory subdirectory) {
|
||||
return map.get(subdirectory);
|
||||
}
|
||||
|
||||
public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
|
||||
ZipEntry ze = new RelativeFile(subdirectory, file).getZipEntry(zfile);
|
||||
return new ZipFileObject(this, file, ze);
|
||||
}
|
||||
|
||||
public Set<RelativeDirectory> getSubdirectories() {
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
zfile.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ZipArchive[" + zfile.getName() + "]";
|
||||
}
|
||||
|
||||
private Path getAbsoluteFile() {
|
||||
Path absFile = (absFileRef == null ? null : absFileRef.get());
|
||||
if (absFile == null) {
|
||||
absFile = Paths.get(zfile.getName()).toAbsolutePath();
|
||||
absFileRef = new SoftReference<>(absFile);
|
||||
}
|
||||
return absFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* The file manager that created this archive.
|
||||
*/
|
||||
protected JavacFileManager fileManager;
|
||||
/**
|
||||
* The index for the contents of this archive.
|
||||
*/
|
||||
protected final Map<RelativeDirectory,List<String>> map;
|
||||
/**
|
||||
* The zip file for the archive.
|
||||
*/
|
||||
protected final ZipFile zfile;
|
||||
/**
|
||||
* A reference to the absolute filename for the zip file for the archive.
|
||||
*/
|
||||
protected Reference<Path> absFileRef;
|
||||
|
||||
/**
|
||||
* A subclass of JavaFileObject representing zip entries.
|
||||
*/
|
||||
public static class ZipFileObject extends BaseFileObject {
|
||||
|
||||
private String name;
|
||||
ZipArchive zarch;
|
||||
ZipEntry entry;
|
||||
|
||||
protected ZipFileObject(ZipArchive zarch, String name, ZipEntry entry) {
|
||||
super(zarch.fileManager);
|
||||
this.zarch = zarch;
|
||||
this.name = name;
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
@DefinedBy(Api.COMPILER)
|
||||
public URI toUri() {
|
||||
Path zipFile = Paths.get(zarch.zfile.getName());
|
||||
return createJarUri(zipFile, entry.getName());
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public String getName() {
|
||||
return zarch.zfile.getName() + "(" + entry.getName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return Paths.get(zarch.zfile.getName()).getFileName() + "(" + entry + ")";
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public JavaFileObject.Kind getKind() {
|
||||
return getKind(entry.getName());
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public InputStream openInputStream() throws IOException {
|
||||
return zarch.zfile.getInputStream(entry);
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||
CharBuffer cb = fileManager.getCachedContent(this);
|
||||
if (cb == null) {
|
||||
try (InputStream in = zarch.zfile.getInputStream(entry)) {
|
||||
ByteBuffer bb = fileManager.makeByteBuffer(in);
|
||||
JavaFileObject prev = fileManager.log.useSource(this);
|
||||
try {
|
||||
cb = fileManager.decode(bb, ignoreEncodingErrors);
|
||||
} finally {
|
||||
fileManager.log.useSource(prev);
|
||||
}
|
||||
fileManager.recycleByteBuffer(bb);
|
||||
if (!ignoreEncodingErrors) {
|
||||
fileManager.cache(this, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public Writer openWriter() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public long getLastModified() {
|
||||
return entry.getTime();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public boolean delete() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
|
||||
return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String inferBinaryName(Iterable<? extends Path> path) {
|
||||
String entryName = entry.getName();
|
||||
return removeExtension(entryName).replace('/', '.');
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
|
||||
Objects.requireNonNull(cn);
|
||||
// null check
|
||||
if (k == Kind.OTHER && getKind() != k) {
|
||||
return false;
|
||||
}
|
||||
return name.equals(cn + k.extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two file objects are equal.
|
||||
* Two ZipFileObjects are equal if the absolute paths of the underlying
|
||||
* zip files are equal and if the paths within those zip files are equal.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other)
|
||||
return true;
|
||||
|
||||
if (!(other instanceof ZipFileObject))
|
||||
return false;
|
||||
|
||||
ZipFileObject o = (ZipFileObject) other;
|
||||
return zarch.getAbsoluteFile().equals(o.zarch.getAbsoluteFile())
|
||||
&& entry.getName().equals(o.entry.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return zarch.getAbsoluteFile().hashCode() + entry.getName().hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,247 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2015, 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.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.file.JavacFileManager.Archive;
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeFile;
|
||||
import com.sun.tools.javac.util.Assert;
|
||||
import com.sun.tools.javac.util.DefinedBy;
|
||||
import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
import com.sun.tools.javac.util.List;
|
||||
|
||||
/**
|
||||
* <p><b>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.</b>
|
||||
*/
|
||||
public class ZipFileIndexArchive implements Archive {
|
||||
|
||||
private final ZipFileIndex zfIndex;
|
||||
private final JavacFileManager fileManager;
|
||||
|
||||
public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
|
||||
super();
|
||||
this.fileManager = fileManager;
|
||||
this.zfIndex = zdir;
|
||||
}
|
||||
|
||||
public boolean contains(RelativePath name) {
|
||||
return zfIndex.contains(name);
|
||||
}
|
||||
|
||||
public List<String> getFiles(RelativeDirectory subdirectory) {
|
||||
return zfIndex.getFiles(subdirectory);
|
||||
}
|
||||
|
||||
public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
|
||||
RelativeFile fullZipFileName = new RelativeFile(subdirectory, file);
|
||||
ZipFileIndex.Entry entry = zfIndex.getZipIndexEntry(fullZipFileName);
|
||||
JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile());
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Set<RelativeDirectory> getSubdirectories() {
|
||||
return zfIndex.getAllDirectories();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
zfIndex.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ZipFileIndexArchive[" + zfIndex + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.file.ZipFileIndex implementation.
|
||||
*/
|
||||
public static class ZipFileIndexFileObject extends BaseFileObject {
|
||||
|
||||
/** The entry's name.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/** The zipfile containing the entry.
|
||||
*/
|
||||
ZipFileIndex zfIndex;
|
||||
|
||||
/** The underlying zip entry object.
|
||||
*/
|
||||
ZipFileIndex.Entry entry;
|
||||
|
||||
/** The name of the zip file where this entry resides.
|
||||
*/
|
||||
Path zipName;
|
||||
|
||||
|
||||
ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, Path zipFileName) {
|
||||
super(fileManager);
|
||||
this.name = entry.getFileName();
|
||||
this.zfIndex = zfIndex;
|
||||
this.entry = entry;
|
||||
this.zipName = zipFileName;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public URI toUri() {
|
||||
return createJarUri(zipName, getPrefixedEntryName());
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public String getName() {
|
||||
return zipName + "(" + getPrefixedEntryName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return zipName.getFileName() + "(" + entry.getName() + ")";
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public JavaFileObject.Kind getKind() {
|
||||
return getKind(entry.getName());
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public InputStream openInputStream() throws IOException {
|
||||
Assert.checkNonNull(entry); // see constructor
|
||||
return new ByteArrayInputStream(zfIndex.read(entry));
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||
CharBuffer cb = fileManager.getCachedContent(this);
|
||||
if (cb == null) {
|
||||
try (InputStream in = new ByteArrayInputStream(zfIndex.read(entry))) {
|
||||
ByteBuffer bb = fileManager.makeByteBuffer(in);
|
||||
JavaFileObject prev = fileManager.log.useSource(this);
|
||||
try {
|
||||
cb = fileManager.decode(bb, ignoreEncodingErrors);
|
||||
} finally {
|
||||
fileManager.log.useSource(prev);
|
||||
}
|
||||
fileManager.recycleByteBuffer(bb); // save for next time
|
||||
if (!ignoreEncodingErrors)
|
||||
fileManager.cache(this, cb);
|
||||
}
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public Writer openWriter() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public long getLastModified() {
|
||||
return entry.getLastModified();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public boolean delete() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
|
||||
return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String inferBinaryName(Iterable<? extends Path> path) {
|
||||
String entryName = entry.getName();
|
||||
if (zfIndex.symbolFilePrefix != null) {
|
||||
String prefix = zfIndex.symbolFilePrefix.path;
|
||||
if (entryName.startsWith(prefix))
|
||||
entryName = entryName.substring(prefix.length());
|
||||
}
|
||||
return removeExtension(entryName).replace('/', '.');
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
|
||||
Objects.requireNonNull(cn);
|
||||
if (k == Kind.OTHER && getKind() != k)
|
||||
return false;
|
||||
return name.equals(cn + k.extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two file objects are equal.
|
||||
* Two ZipFileIndexFileObjects are equal if the absolute paths of the underlying
|
||||
* zip files are equal and if the paths within those zip files are equal.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other)
|
||||
return true;
|
||||
|
||||
if (!(other instanceof ZipFileIndexFileObject))
|
||||
return false;
|
||||
|
||||
ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
|
||||
return zfIndex.getAbsoluteFile().equals(o.zfIndex.getAbsoluteFile())
|
||||
&& entry.equals(o.entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return zfIndex.getAbsoluteFile().hashCode() + entry.hashCode();
|
||||
}
|
||||
|
||||
private String getPrefixedEntryName() {
|
||||
if (zfIndex.symbolFilePrefix != null)
|
||||
return zfIndex.symbolFilePrefix.path + entry.getName();
|
||||
else
|
||||
return entry.getName();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2014, 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.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
|
||||
|
||||
/** A cache for ZipFileIndex objects. */
|
||||
public class ZipFileIndexCache {
|
||||
|
||||
private final Map<Path, ZipFileIndex> map = new HashMap<>();
|
||||
|
||||
/** Get a shared instance of the cache. */
|
||||
private static ZipFileIndexCache sharedInstance;
|
||||
public synchronized static ZipFileIndexCache getSharedInstance() {
|
||||
if (sharedInstance == null)
|
||||
sharedInstance = new ZipFileIndexCache();
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
/** Get a context-specific instance of a cache. */
|
||||
public static ZipFileIndexCache instance(Context context) {
|
||||
ZipFileIndexCache instance = context.get(ZipFileIndexCache.class);
|
||||
if (instance == null)
|
||||
context.put(ZipFileIndexCache.class, instance = new ZipFileIndexCache());
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all ZipFileIndex entries
|
||||
*
|
||||
* @return A list of ZipFileIndex entries, or an empty list
|
||||
*/
|
||||
public List<ZipFileIndex> getZipFileIndexes() {
|
||||
return getZipFileIndexes(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all ZipFileIndex entries
|
||||
*
|
||||
* @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise
|
||||
* all ZipFileEntry(s) are included into the list.
|
||||
* @return A list of ZipFileIndex entries, or an empty list
|
||||
*/
|
||||
public synchronized List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
|
||||
List<ZipFileIndex> zipFileIndexes = new ArrayList<>();
|
||||
|
||||
zipFileIndexes.addAll(map.values());
|
||||
|
||||
if (openedOnly) {
|
||||
for(ZipFileIndex elem : zipFileIndexes) {
|
||||
if (!elem.isOpen()) {
|
||||
zipFileIndexes.remove(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return zipFileIndexes;
|
||||
}
|
||||
|
||||
public synchronized ZipFileIndex getZipFileIndex(Path zipFile,
|
||||
RelativeDirectory symbolFilePrefix,
|
||||
boolean useCache, String cacheLocation,
|
||||
boolean writeIndex) throws IOException {
|
||||
ZipFileIndex zi = getExistingZipIndex(zipFile);
|
||||
|
||||
if (zi == null || (zi != null && Files.getLastModifiedTime(zipFile).toMillis() != zi.zipFileLastModified)) {
|
||||
zi = new ZipFileIndex(zipFile, symbolFilePrefix, writeIndex,
|
||||
useCache, cacheLocation);
|
||||
map.put(zipFile, zi);
|
||||
}
|
||||
return zi;
|
||||
}
|
||||
|
||||
public synchronized ZipFileIndex getExistingZipIndex(Path zipFile) {
|
||||
return map.get(zipFile);
|
||||
}
|
||||
|
||||
public synchronized void clearCache() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public synchronized void clearCache(long timeNotUsed) {
|
||||
for (Path cachedFile : map.keySet()) {
|
||||
ZipFileIndex cachedZipIndex = map.get(cachedFile);
|
||||
if (cachedZipIndex != null) {
|
||||
long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
|
||||
if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
|
||||
System.currentTimeMillis() > timeToTest) {
|
||||
map.remove(cachedFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void removeFromCache(Path file) {
|
||||
map.remove(file);
|
||||
}
|
||||
|
||||
/** Sets already opened list of ZipFileIndexes from an outside client
|
||||
* of the compiler. This functionality should be used in a non-batch clients of the compiler.
|
||||
*/
|
||||
public synchronized void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
|
||||
if (map.isEmpty()) {
|
||||
String msg =
|
||||
"Setting opened indexes should be called only when the ZipFileCache is empty. "
|
||||
+ "Call JavacFileManager.flush() before calling this method.";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
|
||||
for (ZipFileIndex zfi : indexes) {
|
||||
map.put(zfi.zipFile, zfi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,15 +29,18 @@ import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.NestingKind;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.comp.Annotate;
|
||||
import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
|
||||
import com.sun.tools.javac.code.*;
|
||||
@ -47,7 +50,8 @@ import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.Symtab;
|
||||
import com.sun.tools.javac.code.Type.*;
|
||||
import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
|
||||
import com.sun.tools.javac.file.BaseFileObject;
|
||||
import com.sun.tools.javac.file.BaseFileManager;
|
||||
import com.sun.tools.javac.file.PathFileObject;
|
||||
import com.sun.tools.javac.jvm.ClassFile.NameAndType;
|
||||
import com.sun.tools.javac.jvm.ClassFile.Version;
|
||||
import com.sun.tools.javac.util.*;
|
||||
@ -2465,15 +2469,14 @@ public class ClassReader {
|
||||
* to be valid as is, so operations other than those to access the name throw
|
||||
* UnsupportedOperationException
|
||||
*/
|
||||
private static class SourceFileObject extends BaseFileObject {
|
||||
private static class SourceFileObject implements JavaFileObject {
|
||||
|
||||
/** The file's name.
|
||||
*/
|
||||
private Name name;
|
||||
private Name flatname;
|
||||
private final Name name;
|
||||
private final Name flatname;
|
||||
|
||||
public SourceFileObject(Name name, Name flatname) {
|
||||
super(null); // no file manager; never referenced for this file object
|
||||
this.name = name;
|
||||
this.flatname = flatname;
|
||||
}
|
||||
@ -2483,7 +2486,7 @@ public class ClassReader {
|
||||
try {
|
||||
return new URI(null, name.toString(), null);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new CannotCreateUriError(name.toString(), e);
|
||||
throw new PathFileObject.CannotCreateUriError(name.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2492,14 +2495,9 @@ public class ClassReader {
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public JavaFileObject.Kind getKind() {
|
||||
return getKind(getName());
|
||||
return BaseFileManager.getKind(getName());
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
@ -2537,16 +2535,21 @@ public class ClassReader {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String inferBinaryName(Iterable<? extends Path> path) {
|
||||
return flatname.toString();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
|
||||
return true; // fail-safe mode
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public NestingKind getNestingKind() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER)
|
||||
public Modifier getAccessLevel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two file objects are equal.
|
||||
* SourceFileObjects are just placeholder objects for the value of a
|
||||
|
||||
@ -40,7 +40,7 @@ import com.sun.tools.javac.code.Attribute.RetentionPolicy;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.Type.*;
|
||||
import com.sun.tools.javac.code.Types.UniqueType;
|
||||
import com.sun.tools.javac.file.BaseFileObject;
|
||||
import com.sun.tools.javac.file.PathFileObject;
|
||||
import com.sun.tools.javac.jvm.Pool.DynamicMethod;
|
||||
import com.sun.tools.javac.jvm.Pool.Method;
|
||||
import com.sun.tools.javac.jvm.Pool.MethodHandle;
|
||||
@ -52,6 +52,7 @@ import static com.sun.tools.javac.code.Kinds.Kind.*;
|
||||
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
|
||||
import static com.sun.tools.javac.code.TypeTag.*;
|
||||
import static com.sun.tools.javac.main.Option.*;
|
||||
|
||||
import static javax.tools.StandardLocation.CLASS_OUTPUT;
|
||||
|
||||
/** This class provides operations to map an internal symbol table graph
|
||||
@ -1699,7 +1700,7 @@ public class ClassWriter extends ClassFile {
|
||||
// the last possible moment because the sourcefile may be used
|
||||
// elsewhere in error diagnostics. Fixes 4241573.
|
||||
//databuf.appendChar(c.pool.put(c.sourcefile));
|
||||
String simpleName = BaseFileObject.getSimpleName(c.sourcefile);
|
||||
String simpleName = PathFileObject.getSimpleName(c.sourcefile);
|
||||
databuf.appendChar(c.pool.put(names.fromString(simpleName)));
|
||||
endAttr(alenIdx);
|
||||
acount++;
|
||||
|
||||
@ -141,8 +141,11 @@ public class Main {
|
||||
JavacFileManager.preRegister(context); // can't create it until Log has been set up
|
||||
Result result = compile(args, context);
|
||||
if (fileManager instanceof JavacFileManager) {
|
||||
// A fresh context was created above, so jfm must be a JavacFileManager
|
||||
((JavacFileManager)fileManager).close();
|
||||
try {
|
||||
// A fresh context was created above, so jfm must be a JavacFileManager
|
||||
((JavacFileManager)fileManager).close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2015, 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
|
||||
@ -45,7 +45,7 @@ import com.sun.tools.javac.code.Printer;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.code.Type.CapturedType;
|
||||
import com.sun.tools.javac.file.BaseFileObject;
|
||||
import com.sun.tools.javac.file.PathFileObject;
|
||||
import com.sun.tools.javac.jvm.Profile;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.tree.Pretty;
|
||||
@ -144,10 +144,10 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
|
||||
throw new IllegalArgumentException(); // d should have source set
|
||||
if (fullname)
|
||||
return fo.getName();
|
||||
else if (fo instanceof BaseFileObject)
|
||||
return ((BaseFileObject) fo).getShortName();
|
||||
else if (fo instanceof PathFileObject)
|
||||
return ((PathFileObject) fo).getShortName();
|
||||
else
|
||||
return BaseFileObject.getSimpleName(fo);
|
||||
return PathFileObject.getSimpleName(fo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2015, 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
|
||||
@ -31,7 +31,7 @@ import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.*;
|
||||
import com.sun.tools.javac.api.Formattable;
|
||||
import com.sun.tools.javac.file.BaseFileObject;
|
||||
import com.sun.tools.javac.file.PathFileObject;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
|
||||
|
||||
@ -123,8 +123,8 @@ public final class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
|
||||
} else if (arg instanceof JCExpression) {
|
||||
JCExpression tree = (JCExpression)arg;
|
||||
s = "@" + tree.getStartPosition();
|
||||
} else if (arg instanceof BaseFileObject) {
|
||||
s = ((BaseFileObject) arg).getShortName();
|
||||
} else if (arg instanceof PathFileObject) {
|
||||
s = ((PathFileObject) arg).getShortName();
|
||||
} else {
|
||||
s = super.formatArgument(diag, arg, null);
|
||||
}
|
||||
|
||||
@ -115,7 +115,11 @@ public class SjavacImpl implements Sjavac {
|
||||
// Clean up
|
||||
JavaFileManager fileManager = context.get(JavaFileManager.class);
|
||||
if (fileManager instanceof JavacFileManager) {
|
||||
((JavacFileManager) fileManager).close();
|
||||
try {
|
||||
((JavacFileManager) fileManager).close();
|
||||
} catch (IOException e) {
|
||||
return RC_FATAL;
|
||||
}
|
||||
}
|
||||
return result.exitCode;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2015, 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
|
||||
@ -103,10 +103,14 @@ public class SourcePositionImpl implements SourcePosition {
|
||||
String fn = filename.getName();
|
||||
if (fn.endsWith(")")) {
|
||||
int paren = fn.lastIndexOf("(");
|
||||
if (paren != -1)
|
||||
if (paren != -1) {
|
||||
int i = paren+1;
|
||||
if (fn.charAt(i) == '/')
|
||||
i++;
|
||||
fn = fn.substring(0, paren)
|
||||
+ File.separatorChar
|
||||
+ fn.substring(paren + 1, fn.length() - 1);
|
||||
+ fn.substring(i, fn.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (position == Position.NOPOS)
|
||||
|
||||
@ -53,9 +53,6 @@ import static javax.tools.StandardLocation.*;
|
||||
* the impl of inferBinaryName for that file object.
|
||||
*/
|
||||
public class TestInferBinaryName {
|
||||
static final boolean DONT_USE_ZIP_FILE_INDEX = false;
|
||||
static final boolean USE_ZIP_FILE_INDEX = true;
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
new TestInferBinaryName().run();
|
||||
}
|
||||
@ -64,10 +61,7 @@ public class TestInferBinaryName {
|
||||
testDirectory();
|
||||
|
||||
File testJar = createJar();
|
||||
|
||||
testZipArchive(testJar);
|
||||
testZipFileIndexArchive(testJar);
|
||||
testZipFileIndexArchive2(testJar);
|
||||
|
||||
if (errors > 0)
|
||||
throw new Exception(errors + " error found");
|
||||
@ -87,40 +81,18 @@ public class TestInferBinaryName {
|
||||
void testDirectory() throws IOException {
|
||||
String testClassName = "p.A";
|
||||
List<File> testClasses = Arrays.asList(new File(System.getProperty("test.classes")));
|
||||
try (JavaFileManager fm =
|
||||
getFileManager(testClasses, USE_ZIP_FILE_INDEX)) {
|
||||
try (JavaFileManager fm = getFileManager(testClasses)) {
|
||||
test("testDirectory",
|
||||
fm, testClassName, "com.sun.tools.javac.file.RegularFileObject");
|
||||
fm, testClassName, "SimpleFileObject");
|
||||
}
|
||||
}
|
||||
|
||||
void testZipArchive(File testJar) throws IOException {
|
||||
String testClassName = "java.lang.String";
|
||||
List<File> path = Arrays.asList(testJar);
|
||||
try (JavaFileManager fm =
|
||||
getFileManager(path, DONT_USE_ZIP_FILE_INDEX)) {
|
||||
try (JavaFileManager fm = getFileManager(path)) {
|
||||
test("testZipArchive",
|
||||
fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject");
|
||||
}
|
||||
}
|
||||
|
||||
void testZipFileIndexArchive(File testJar) throws IOException {
|
||||
String testClassName = "java.lang.String";
|
||||
List<File> path = Arrays.asList(testJar);
|
||||
try (JavaFileManager fm =
|
||||
getFileManager(path, USE_ZIP_FILE_INDEX)) {
|
||||
test("testZipFileIndexArchive",
|
||||
fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
|
||||
}
|
||||
}
|
||||
|
||||
void testZipFileIndexArchive2(File testJar) throws IOException {
|
||||
String testClassName = "java.lang.String";
|
||||
List<File> path = Arrays.asList(testJar);
|
||||
try (JavaFileManager fm =
|
||||
getFileManager(path, USE_ZIP_FILE_INDEX)) {
|
||||
test("testZipFileIndexArchive2",
|
||||
fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
|
||||
fm, testClassName, "JarFileObject");
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,21 +113,17 @@ public class TestInferBinaryName {
|
||||
return;
|
||||
}
|
||||
|
||||
String cn = fo.getClass().getName();
|
||||
String cn = fo.getClass().getSimpleName();
|
||||
String bn = fm.inferBinaryName(CLASS_PATH, fo);
|
||||
System.err.println(testName + " " + cn + " " + bn);
|
||||
check(cn, implClassName);
|
||||
check(bn, testClassName);
|
||||
checkEqual(cn, implClassName);
|
||||
checkEqual(bn, testClassName);
|
||||
System.err.println("OK");
|
||||
}
|
||||
|
||||
JavaFileManager getFileManager(List<File> path,
|
||||
boolean zipFileIndexKind)
|
||||
JavaFileManager getFileManager(List<File> path)
|
||||
throws IOException {
|
||||
Context ctx = new Context();
|
||||
Options options = Options.instance(ctx);
|
||||
options.put("useOptimizedZip",
|
||||
Boolean.toString(zipFileIndexKind == USE_ZIP_FILE_INDEX));
|
||||
|
||||
JavacFileManager fm = new JavacFileManager(ctx, false, null);
|
||||
fm.setLocation(CLASS_PATH, path);
|
||||
@ -163,7 +131,7 @@ public class TestInferBinaryName {
|
||||
}
|
||||
|
||||
List<File> getPath(String s) {
|
||||
List<File> path = new ArrayList<File>();
|
||||
List<File> path = new ArrayList<>();
|
||||
for (String f: s.split(File.pathSeparator)) {
|
||||
if (f.length() > 0)
|
||||
path.add(new File(f));
|
||||
@ -172,7 +140,7 @@ public class TestInferBinaryName {
|
||||
return path;
|
||||
}
|
||||
|
||||
void check(String found, String expect) {
|
||||
void checkEqual(String found, String expect) {
|
||||
if (!found.equals(expect)) {
|
||||
System.err.println("Expected: " + expect);
|
||||
System.err.println(" Found: " + found);
|
||||
|
||||
@ -53,7 +53,7 @@ public class T6358024 extends AbstractProcessor {
|
||||
String testSrc = System.getProperty("test.src");
|
||||
|
||||
fm = new JavacFileManager(new Context(), false, null);
|
||||
JavaFileObject f = fm.getFileForInput(testSrc + File.separatorChar + self + ".java");
|
||||
JavaFileObject f = fm.getJavaFileObject(testSrc + File.separatorChar + self + ".java");
|
||||
|
||||
test(fm, f,
|
||||
new Option[] { new Option("-d", ".")},
|
||||
|
||||
@ -54,7 +54,7 @@ public class T6358166 extends AbstractProcessor {
|
||||
String testSrc = System.getProperty("test.src");
|
||||
|
||||
JavacFileManager fm = new JavacFileManager(new Context(), false, null);
|
||||
JavaFileObject f = fm.getFileForInput(testSrc + File.separatorChar + self + ".java");
|
||||
JavaFileObject f = fm.getJavaFileObject(testSrc + File.separatorChar + self + ".java");
|
||||
|
||||
test(fm, f, "-verbose", "-d", ".");
|
||||
|
||||
|
||||
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6705935
|
||||
* @summary javac reports path name of entry in ZipFileIndex incorectly
|
||||
* @modules jdk.compiler/com.sun.tools.javac.file
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.tools.*;
|
||||
import com.sun.tools.javac.file.*;
|
||||
import com.sun.tools.javac.file.ZipArchive.ZipFileObject;
|
||||
import com.sun.tools.javac.file.ZipFileIndexArchive.ZipFileIndexFileObject;
|
||||
|
||||
public class T6705935 {
|
||||
public static void main(String... args) throws Exception {
|
||||
new T6705935().run();
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
File java_home = new File(System.getProperty("java.home"));
|
||||
|
||||
JavaCompiler c = ToolProvider.getSystemJavaCompiler();
|
||||
try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) {
|
||||
//System.err.println("platform class path: " + asList(fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)));
|
||||
|
||||
for (JavaFileObject fo: fm.list(StandardLocation.PLATFORM_CLASS_PATH,
|
||||
"java.lang",
|
||||
Collections.singleton(JavaFileObject.Kind.CLASS),
|
||||
false)) {
|
||||
test++;
|
||||
|
||||
if (!(fo instanceof ZipFileObject || fo instanceof ZipFileIndexFileObject)) {
|
||||
System.out.println("Skip " + fo.getClass().getSimpleName() + " " + fo.getName());
|
||||
skip++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//System.err.println(fo.getName());
|
||||
String p = fo.getName();
|
||||
int bra = p.indexOf("(");
|
||||
int ket = p.indexOf(")");
|
||||
//System.err.println(bra + "," + ket + "," + p.length());
|
||||
if (bra == -1 || ket != p.length() -1)
|
||||
throw new Exception("unexpected path: " + p + "[" + bra + "," + ket + "," + p.length());
|
||||
String part1 = p.substring(0, bra);
|
||||
String part2 = p.substring(bra + 1, ket);
|
||||
//System.err.println("[" + part1 + "|" + part2 + "]" + " " + java_home);
|
||||
if (part1.equals(part2) || !part1.startsWith(java_home.getPath()))
|
||||
throw new Exception("bad path: " + p);
|
||||
|
||||
}
|
||||
|
||||
if (test == 0)
|
||||
throw new Exception("no files found");
|
||||
|
||||
if (skip == 0)
|
||||
System.out.println(test + " files found");
|
||||
else
|
||||
System.out.println(test + " files found, " + skip + " files skipped");
|
||||
|
||||
if (test == skip)
|
||||
System.out.println("Warning: all files skipped; no platform classes found in zip files.");
|
||||
}
|
||||
}
|
||||
|
||||
private <T> List<T> asList(Iterable<? extends T> items) {
|
||||
List<T> list = new ArrayList<T>();
|
||||
for (T item: items)
|
||||
list.add(item);
|
||||
return list;
|
||||
}
|
||||
|
||||
private int skip;
|
||||
private int test;
|
||||
}
|
||||
@ -37,16 +37,15 @@
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import javax.tools.*;
|
||||
|
||||
import com.sun.tools.javac.file.JavacFileManager;
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeFile;
|
||||
import com.sun.tools.javac.file.ZipFileIndex;
|
||||
import com.sun.tools.javac.file.ZipFileIndexArchive;
|
||||
import com.sun.tools.javac.file.ZipFileIndexCache;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
|
||||
public class T6725036 {
|
||||
@ -63,21 +62,14 @@ public class T6725036 {
|
||||
JarEntry je = j.getJarEntry(TEST_ENTRY_NAME.getPath());
|
||||
long jarEntryTime = je.getTime();
|
||||
|
||||
ZipFileIndexCache zfic = ZipFileIndexCache.getSharedInstance();
|
||||
ZipFileIndex zfi = zfic.getZipFileIndex(testJar.toPath(), null, false, null, false);
|
||||
long zfiTime = zfi.getLastModified(TEST_ENTRY_NAME);
|
||||
|
||||
check(je, jarEntryTime, zfi + ":" + TEST_ENTRY_NAME.getPath(), zfiTime);
|
||||
|
||||
Context context = new Context();
|
||||
JavacFileManager fm = new JavacFileManager(context, false, null);
|
||||
ZipFileIndexArchive zfia = new ZipFileIndexArchive(fm, zfi);
|
||||
JavaFileObject jfo =
|
||||
zfia.getFileObject(TEST_ENTRY_NAME.dirname(),
|
||||
TEST_ENTRY_NAME.basename());
|
||||
long jfoTime = jfo.getLastModified();
|
||||
fm.setLocation(StandardLocation.CLASS_PATH, Collections.singletonList(testJar));
|
||||
FileObject fo =
|
||||
fm.getFileForInput(StandardLocation.CLASS_PATH, "", TEST_ENTRY_NAME.getPath());
|
||||
long jfoTime = fo.getLastModified();
|
||||
|
||||
check(je, jarEntryTime, jfo, jfoTime);
|
||||
check(je, jarEntryTime, fo, jfoTime);
|
||||
|
||||
if (errors > 0)
|
||||
throw new Exception(errors + " occurred");
|
||||
|
||||
@ -55,19 +55,13 @@ public class T6440528 extends ToolTester {
|
||||
"package-info.class",
|
||||
src);
|
||||
File expect = new File(test_src, "package-info.class");
|
||||
File got = getUnderlyingFile(cls);
|
||||
File got = fm.asPath(cls).toFile();
|
||||
if (!got.equals(expect))
|
||||
throw new AssertionError(String.format("Expected: %s; got: %s", expect, got));
|
||||
System.err.println("Expected: " + expect);
|
||||
System.err.println("Got: " + got);
|
||||
}
|
||||
|
||||
private File getUnderlyingFile(FileObject o) throws Exception {
|
||||
Field file = o.getClass().getDeclaredField("file"); // assumes RegularFileObject
|
||||
file.setAccessible(true);
|
||||
return ((Path)file.get(o)).toFile();
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
try (T6440528 t = new T6440528()) {
|
||||
t.test(args);
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 6358955
|
||||
* @summary JavacFileManager.getFileForInput(dir) shuld throw IAE
|
||||
* @summary JavacFileManager.getFileForInput(dir) should throw IAE
|
||||
* @modules java.compiler
|
||||
* jdk.compiler
|
||||
*/
|
||||
|
||||
@ -32,18 +32,18 @@
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
import javax.tools.*;
|
||||
import javax.tools.JavaFileManager.Location;
|
||||
|
||||
import com.sun.tools.javac.file.JavacFileManager;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.Options;
|
||||
|
||||
public class T6838467 {
|
||||
boolean fileSystemIsCaseSignificant = !new File("a").equals(new File("A"));
|
||||
|
||||
enum FileKind {
|
||||
DIR("dir"),
|
||||
ZIP("zip"),
|
||||
ZIPFILEINDEX("zip");
|
||||
ZIP("zip");
|
||||
FileKind(String path) {
|
||||
file = new File(path);
|
||||
}
|
||||
@ -52,15 +52,19 @@ public class T6838467 {
|
||||
|
||||
enum CompareKind {
|
||||
SAME {
|
||||
@Override
|
||||
File other(File f) { return f; }
|
||||
},
|
||||
ABSOLUTE {
|
||||
@Override
|
||||
File other(File f) { return f.getAbsoluteFile(); }
|
||||
},
|
||||
DIFFERENT {
|
||||
@Override
|
||||
File other(File f) { return new File("not_" + f.getPath()); }
|
||||
},
|
||||
CASEEQUIV {
|
||||
@Override
|
||||
File other(File f) { return new File(f.getPath().toUpperCase()); }
|
||||
};
|
||||
abstract File other(File f);
|
||||
@ -73,10 +77,17 @@ public class T6838467 {
|
||||
}
|
||||
|
||||
void run() throws Exception {
|
||||
boolean fileNameIsCaseSignificant = isFileNameCaseSignificant();
|
||||
boolean fileLookupIsCaseSignificant = isFileLookupCaseSignificant();
|
||||
|
||||
String osName = System.getProperty("os.name");
|
||||
System.err.println("OS: " + osName);
|
||||
System.err.println("fileNameIsCaseSignificant:" + fileNameIsCaseSignificant);
|
||||
System.err.println("fileLookupIsCaseSignificant:" + fileLookupIsCaseSignificant);
|
||||
|
||||
// on Windows, verify file system is not case significant
|
||||
if (System.getProperty("os.name").toLowerCase().startsWith("windows")
|
||||
&& fileSystemIsCaseSignificant) {
|
||||
error("fileSystemIsCaseSignificant is set on Windows.");
|
||||
if ((osName.startsWith("windows")) && fileNameIsCaseSignificant) {
|
||||
error("fileNameIsCaseSignificant is set on " + osName + ".");
|
||||
}
|
||||
|
||||
// create a set of directories and zip files to compare
|
||||
@ -84,7 +95,7 @@ public class T6838467 {
|
||||
createTestDir(new File("not_dir"), paths);
|
||||
createTestZip(new File("zip"), paths);
|
||||
createTestZip(new File("not_zip"), paths);
|
||||
if (fileSystemIsCaseSignificant) {
|
||||
if (fileNameIsCaseSignificant || fileLookupIsCaseSignificant) {
|
||||
createTestDir(new File("DIR"), paths);
|
||||
createTestZip(new File("ZIP"), paths);
|
||||
}
|
||||
@ -99,8 +110,9 @@ public class T6838467 {
|
||||
|
||||
// verify that the various different types of file object were all
|
||||
// tested
|
||||
Set<String> expectClasses = new HashSet<String>(Arrays.asList(
|
||||
"RegularFileObject", "ZipFileObject", "ZipFileIndexFileObject" ));
|
||||
Set<String> expectClasses = new HashSet<>(Arrays.asList(
|
||||
"DirectoryFileObject",
|
||||
"JarFileObject" ));
|
||||
if (!foundClasses.equals(expectClasses)) {
|
||||
error("expected fileobject classes not found\n"
|
||||
+ "expected: " + expectClasses + "\n"
|
||||
@ -112,26 +124,22 @@ public class T6838467 {
|
||||
}
|
||||
|
||||
void test(FileKind fk, CompareKind ck) throws IOException {
|
||||
File f1 = fk.file;
|
||||
JavaFileManager fm1 = createFileManager(fk, f1);
|
||||
try (StandardJavaFileManager fm = createFileManager()) {
|
||||
File f1 = fk.file;
|
||||
Location l1 = createLocation(fm, "l1", f1);
|
||||
|
||||
File f2 = ck.other(fk.file);
|
||||
JavaFileManager fm2 = createFileManager(fk, f2);
|
||||
File f2 = ck.other(fk.file);
|
||||
Location l2 = createLocation(fm, "l2", f2);
|
||||
|
||||
try {
|
||||
// If the directories or zip files match, we expect "n" matches in
|
||||
// the "n-squared" comparisons to come, where "n" is the number of
|
||||
// entries in the the directories or zip files.
|
||||
// If the directories or zip files don't themselves match,
|
||||
// we obviously don't expect any of their contents to match either.
|
||||
int expect = (f1.getAbsoluteFile().equals(f2.getAbsoluteFile()) ? paths.length : 0);
|
||||
int expectEqualCount = (f1.getCanonicalFile().equals(f2.getCanonicalFile()) ? paths.length : 0);
|
||||
|
||||
System.err.println("test " + (++count) + " " + fk + " " + ck + " " + f1 + " " + f2);
|
||||
test(fm1, fm2, expect);
|
||||
|
||||
} finally {
|
||||
fm1.close();
|
||||
fm2.close();
|
||||
test(fm, l1, l2, expectEqualCount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,17 +148,17 @@ public class T6838467 {
|
||||
// returned from the other. For each pair of files, verify that if they
|
||||
// are equal, the hashcode is equal as well, and finally verify that the
|
||||
// expected number of matches was found.
|
||||
void test(JavaFileManager fm1, JavaFileManager fm2, int expectEqualCount) throws IOException {
|
||||
void test(JavaFileManager fm, Location l1, Location l2, int expectEqualCount) throws IOException {
|
||||
boolean foundFiles1 = false;
|
||||
boolean foundFiles2 = false;
|
||||
int foundEqualCount = 0;
|
||||
Set<JavaFileObject.Kind> kinds = EnumSet.allOf(JavaFileObject.Kind.class);
|
||||
for (FileObject fo1: fm1.list(StandardLocation.CLASS_PATH, "p", kinds, false)) {
|
||||
for (FileObject fo1: fm.list(l1, "p", kinds, false)) {
|
||||
foundFiles1 = true;
|
||||
foundClasses.add(fo1.getClass().getSimpleName());
|
||||
for (FileObject fo2: fm2.list(StandardLocation.CLASS_PATH, "p", kinds, false)) {
|
||||
for (FileObject fo2: fm.list(l2, "p", kinds, false)) {
|
||||
foundFiles2 = true;
|
||||
foundClasses.add(fo1.getClass().getSimpleName());
|
||||
foundClasses.add(fo2.getClass().getSimpleName());
|
||||
System.err.println("compare " + fo1 + " " + fo2);
|
||||
if (fo1.equals(fo2)) {
|
||||
foundEqualCount++;
|
||||
@ -163,26 +171,35 @@ public class T6838467 {
|
||||
}
|
||||
}
|
||||
if (!foundFiles1)
|
||||
error("no files found for file manager 1");
|
||||
error("no files found for location " + l1);
|
||||
if (!foundFiles2)
|
||||
error("no files found for file manager 2");
|
||||
error("no files found for location " + l2);
|
||||
// verify the expected number of matches were found
|
||||
if (foundEqualCount != expectEqualCount)
|
||||
error("expected matches not found: expected " + expectEqualCount + ", found " + foundEqualCount);
|
||||
}
|
||||
|
||||
// create a file manager to test a FileKind, with a given directory
|
||||
// or zip file placed on the classpath
|
||||
JavaFileManager createFileManager(FileKind fk, File classpath) throws IOException {
|
||||
StandardJavaFileManager fm = createFileManager(fk == FileKind.ZIP);
|
||||
fm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(classpath));
|
||||
return fm;
|
||||
// create and initialize a location to test a FileKind, with a given directory
|
||||
// or zip file placed on the path
|
||||
Location createLocation(StandardJavaFileManager fm, String name, File classpath) throws IOException {
|
||||
Location l = new Location() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOutputLocation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
fm.setLocation(l, Arrays.asList(classpath));
|
||||
return l;
|
||||
}
|
||||
|
||||
JavacFileManager createFileManager(boolean useOptimizedZip) {
|
||||
JavacFileManager createFileManager() {
|
||||
Context ctx = new Context();
|
||||
Options options = Options.instance(ctx);
|
||||
options.put("useOptimizedZip", Boolean.toString(useOptimizedZip));
|
||||
return new JavacFileManager(ctx, false, null);
|
||||
}
|
||||
|
||||
@ -191,21 +208,17 @@ public class T6838467 {
|
||||
for (String p: paths) {
|
||||
File file = new File(dir, p);
|
||||
file.getParentFile().mkdirs();
|
||||
FileWriter out = new FileWriter(file);
|
||||
try {
|
||||
try (FileWriter out = new FileWriter(file)) {
|
||||
out.write(p);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create a sip file containing a given set of entries
|
||||
// create a zip file containing a given set of entries
|
||||
void createTestZip(File zip, String[] paths) throws IOException {
|
||||
if (zip.getParentFile() != null)
|
||||
zip.getParentFile().mkdirs();
|
||||
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
|
||||
try {
|
||||
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) {
|
||||
for (String p: paths) {
|
||||
ZipEntry ze = new ZipEntry(p);
|
||||
zos.putNextEntry(ze);
|
||||
@ -213,8 +226,6 @@ public class T6838467 {
|
||||
zos.write(bytes, 0, bytes.length);
|
||||
zos.closeEntry();
|
||||
}
|
||||
} finally {
|
||||
zos.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,8 +234,24 @@ public class T6838467 {
|
||||
errors++;
|
||||
}
|
||||
|
||||
boolean isFileNameCaseSignificant() {
|
||||
File lower = new File("test.txt");
|
||||
File upper = new File(lower.getPath().toUpperCase());
|
||||
return !lower.equals(upper);
|
||||
}
|
||||
|
||||
boolean isFileLookupCaseSignificant() throws IOException {
|
||||
File lower = new File("test.txt");
|
||||
File upper = new File(lower.getPath().toUpperCase());
|
||||
if (upper.exists()) {
|
||||
upper.delete();
|
||||
}
|
||||
try (FileWriter out = new FileWriter(lower)) { }
|
||||
return !upper.exists();
|
||||
}
|
||||
|
||||
int count;
|
||||
int errors;
|
||||
Set<String> foundClasses = new HashSet<String>();
|
||||
Set<String> foundClasses = new HashSet<>();
|
||||
}
|
||||
|
||||
|
||||
@ -62,15 +62,12 @@ public class T6877206 {
|
||||
|
||||
test(createFileManager(), createDir("dir", entries), "p", entries.length);
|
||||
test(createFileManager(), createDir("a b/dir", entries), "p", entries.length);
|
||||
|
||||
for (boolean useOptimizedZip: new boolean[] { false, true }) {
|
||||
test(createFileManager(useOptimizedZip), createJar("jar", entries), "p", entries.length);
|
||||
test(createFileManager(useOptimizedZip), createJar("jar jar", entries), "p", entries.length);
|
||||
}
|
||||
test(createFileManager(), createJar("jar", entries), "p", entries.length);
|
||||
test(createFileManager(), createJar("jar jar", entries), "p", entries.length);
|
||||
|
||||
// Verify that we hit the files we intended
|
||||
checkCoverage("classes", foundClasses,
|
||||
"RegularFileObject", "ZipFileIndexFileObject", "ZipFileObject");
|
||||
"DirectoryFileObject", "JarFileObject");
|
||||
|
||||
// Verify that we hit the jar files we intended
|
||||
checkCoverage("jar files", foundJars, "jar", "jar jar");
|
||||
@ -153,17 +150,12 @@ public class T6877206 {
|
||||
}
|
||||
|
||||
JavacFileManager createFileManager() {
|
||||
return createFileManager(false, false);
|
||||
return createFileManager(false);
|
||||
}
|
||||
|
||||
JavacFileManager createFileManager(boolean useOptimizedZip) {
|
||||
return createFileManager(useOptimizedZip, false);
|
||||
}
|
||||
|
||||
JavacFileManager createFileManager(boolean useOptimizedZip, boolean useSymbolFile) {
|
||||
JavacFileManager createFileManager(boolean useSymbolFile) {
|
||||
Context ctx = new Context();
|
||||
Options options = Options.instance(ctx);
|
||||
options.put("useOptimizedZip", Boolean.toString(useOptimizedZip));
|
||||
if (!useSymbolFile) {
|
||||
options.put("ignore.symbol.file", "true");
|
||||
}
|
||||
|
||||
@ -60,7 +60,6 @@ public class T8076104 extends AbstractProcessor {
|
||||
void run() throws Exception {
|
||||
File testJar = createJar();
|
||||
doTest(testJar);
|
||||
doTest(testJar, "-XDuseOptimizedZip=false");
|
||||
}
|
||||
|
||||
File createJar() throws Exception {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2015, 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
|
||||
@ -136,8 +136,11 @@ public class Tester {
|
||||
} catch (IllegalArgumentException | IllegalStateException | IOException e) {
|
||||
tr.setThrown(e);
|
||||
} finally {
|
||||
((JavacFileManager) context.get(JavaFileManager.class)).close();
|
||||
tr.setLogs(sw.toString(), sysOut.close(), sysErr.close());
|
||||
try {
|
||||
((JavacFileManager) context.get(JavaFileManager.class)).close();
|
||||
tr.setLogs(sw.toString(), sysOut.close(), sysErr.close());
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
tr.setContext(context);
|
||||
tr.show();
|
||||
@ -149,6 +152,7 @@ public class Tester {
|
||||
class TestResult {
|
||||
final List<String> args;
|
||||
Throwable thrown;
|
||||
List<Throwable> suppressed = new ArrayList<>();
|
||||
Object rc; // Number or Boolean
|
||||
Map<Log, String> logs;
|
||||
Context context;
|
||||
@ -172,6 +176,10 @@ public class Tester {
|
||||
this.rc = ok ? 0 : 1;
|
||||
}
|
||||
|
||||
void setSuppressed(Throwable thrown) {
|
||||
this.suppressed.add(thrown);
|
||||
}
|
||||
|
||||
void setThrown(Throwable thrown) {
|
||||
this.thrown = thrown;
|
||||
}
|
||||
@ -199,6 +207,11 @@ public class Tester {
|
||||
out.print("thrown:" + thrown);
|
||||
needSep = true;
|
||||
}
|
||||
if (!suppressed.isEmpty()) {
|
||||
if (needSep) out.print("; ");
|
||||
out.print("suppressed:" + suppressed);
|
||||
needSep = true;
|
||||
}
|
||||
if (needSep)
|
||||
out.println();
|
||||
logs.forEach((k, v) -> {
|
||||
|
||||
@ -49,7 +49,7 @@ public class T4910483 {
|
||||
|
||||
String testSrc = System.getProperty("test.src");
|
||||
JavacFileManager fm = new JavacFileManager(new Context(), false, null);
|
||||
JavaFileObject f = fm.getFileForInput(testSrc + File.separatorChar + "T4910483.java");
|
||||
JavaFileObject f = fm.getJavaFileObject(testSrc + File.separatorChar + "T4910483.java");
|
||||
|
||||
JCTree.JCCompilationUnit cu = compiler.parse(f);
|
||||
JCTree classDef = cu.getTypeDecls().head;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2015, 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
|
||||
@ -88,7 +88,7 @@ public class Processor extends AbstractProcessor {
|
||||
if (!testFile.canRead()) throw new IllegalStateException("Cannot read the test source");
|
||||
JavacTool compiler = JavacTool.create();
|
||||
JavacFileManager fm = compiler.getStandardFileManager(null, null, null);
|
||||
testContent = fm.getRegularFile(testFile.toPath()).getCharContent(true).toString();
|
||||
testContent = fm.getJavaFileObject(testFile.toPath()).getCharContent(true).toString();
|
||||
JavaFileObject testFileObject = new TestFO(new URI("mem://" + args[0]), testContent);
|
||||
TestFM testFileManager = new TestFM(fm);
|
||||
JavacTask task = compiler.getTask(null,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2015, 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
|
||||
@ -71,7 +71,7 @@ public class Processor extends AbstractProcessor {
|
||||
File inp = new File(sp, args[0]);
|
||||
|
||||
if (inp.canRead()) {
|
||||
testContent = fm.getRegularFile(inp.toPath()).getCharContent(true).toString();
|
||||
testContent = fm.getJavaFileObject(inp.toPath()).getCharContent(true).toString();
|
||||
}
|
||||
}
|
||||
if (testContent == null) throw new IllegalStateException();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2015, 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
|
||||
@ -74,7 +74,7 @@ public class VerifySuppressWarnings {
|
||||
File inp = new File(sp, args[0]);
|
||||
|
||||
if (inp.canRead()) {
|
||||
testContent = fm.getRegularFile(inp.toPath()).getCharContent(true).toString();
|
||||
testContent = fm.getJavaFileObject(inp.toPath()).getCharContent(true).toString();
|
||||
}
|
||||
}
|
||||
if (testContent == null) throw new IllegalStateException();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user