8076420: Consolidate javac file handling in javac.file package
Reviewed-by: jlahoda
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Thu Apr 02 15:56:07 2015 -0700
@@ -40,6 +40,7 @@
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.comp.*;
+import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.main.*;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.parser.Parser;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java Thu Apr 02 15:56:07 2015 -0700
@@ -44,7 +44,7 @@
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.Arguments;
import com.sun.tools.javac.main.Option;
-import com.sun.tools.javac.util.BaseFileManager;
+import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DefinedBy;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Thu Apr 02 15:56:07 2015 -0700
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2009, 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.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+
+import com.sun.tools.javac.code.Lint;
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.FSInfo;
+import com.sun.tools.javac.file.Locations;
+import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.main.OptionHelper;
+import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.DefinedBy;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Options;
+
+/**
+ * Utility methods for building a filemanager.
+ * There are no references here to file-system specific objects such as
+ * java.io.File or java.nio.file.Path.
+ */
+public abstract class BaseFileManager implements JavaFileManager {
+ protected BaseFileManager(Charset charset) {
+ this.charset = charset;
+ byteBufferCache = new ByteBufferCache();
+ locations = createLocations();
+ }
+
+ /**
+ * Set the context for JavacPathFileManager.
+ * @param context the context containing items to be associated with the file manager
+ */
+ public void setContext(Context context) {
+ log = Log.instance(context);
+ options = Options.instance(context);
+ classLoaderClass = options.get("procloader");
+ locations.update(log, Lint.instance(context), FSInfo.instance(context));
+ }
+
+ protected Locations createLocations() {
+ return new Locations();
+ }
+
+ /**
+ * The log to be used for error reporting.
+ */
+ public Log log;
+
+ /**
+ * User provided charset (through javax.tools).
+ */
+ protected Charset charset;
+
+ protected Options options;
+
+ protected String classLoaderClass;
+
+ protected Locations locations;
+
+ /**
+ * A flag for clients to use to indicate that this file manager should
+ * be closed when it is no longer required.
+ */
+ public boolean autoClose;
+
+ protected Source getSource() {
+ String sourceName = options.get(Option.SOURCE);
+ Source source = null;
+ if (sourceName != null)
+ source = Source.lookup(sourceName);
+ return (source != null ? source : Source.DEFAULT);
+ }
+
+ protected ClassLoader getClassLoader(URL[] urls) {
+ ClassLoader thisClassLoader = getClass().getClassLoader();
+
+ // Allow the following to specify a closeable classloader
+ // other than URLClassLoader.
+
+ // 1: Allow client to specify the class to use via hidden option
+ if (classLoaderClass != null) {
+ try {
+ Class<? extends ClassLoader> loader =
+ Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
+ Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
+ Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
+ return constr.newInstance(urls, thisClassLoader);
+ } catch (ReflectiveOperationException t) {
+ // ignore errors loading user-provided class loader, fall through
+ }
+ }
+ return new URLClassLoader(urls, thisClassLoader);
+ }
+
+ public boolean isDefaultBootClassPath() {
+ return locations.isDefaultBootClassPath();
+ }
+
+ // <editor-fold defaultstate="collapsed" desc="Option handling">
+ @Override @DefinedBy(Api.COMPILER)
+ public boolean handleOption(String current, Iterator<String> remaining) {
+ OptionHelper helper = new GrumpyHelper(log) {
+ @Override
+ public String get(Option option) {
+ return options.get(option.getText());
+ }
+
+ @Override
+ public void put(String name, String value) {
+ options.put(name, value);
+ }
+
+ @Override
+ public void remove(String name) {
+ options.remove(name);
+ }
+
+ @Override
+ public boolean handleFileManagerOption(Option option, String value) {
+ return handleOption(option, value);
+ }
+ };
+
+ for (Option o: javacFileManagerOptions) {
+ if (o.matches(current)) {
+ if (o.hasArg()) {
+ if (remaining.hasNext()) {
+ if (!o.process(helper, current, remaining.next()))
+ return true;
+ }
+ } else {
+ if (!o.process(helper, current))
+ return true;
+ }
+ // operand missing, or process returned true
+ throw new IllegalArgumentException(current);
+ }
+ }
+
+ return false;
+ }
+ // where
+ private static final Set<Option> javacFileManagerOptions =
+ Option.getJavacFileManagerOptions();
+
+ @Override @DefinedBy(Api.COMPILER)
+ public int isSupportedOption(String option) {
+ for (Option o : javacFileManagerOptions) {
+ if (o.matches(option))
+ return o.hasArg() ? 1 : 0;
+ }
+ return -1;
+ }
+
+ /**
+ * Common back end for OptionHelper handleFileManagerOption.
+ * @param option the option whose value to be set
+ * @param value the value for the option
+ * @return true if successful, and false otherwise
+ */
+ public boolean handleOption(Option option, String value) {
+ return locations.handleOption(option, value);
+ }
+
+ /**
+ * Call handleOption for collection of options and corresponding values.
+ * @param map a collection of options and corresponding values
+ * @return true if all the calls are successful
+ */
+ public boolean handleOptions(Map<Option, String> map) {
+ boolean ok = true;
+ for (Map.Entry<Option, String> e: map.entrySet())
+ ok = ok & handleOption(e.getKey(), e.getValue());
+ return ok;
+ }
+
+ // </editor-fold>
+
+ // <editor-fold defaultstate="collapsed" desc="Encoding">
+ private String defaultEncodingName;
+ private String getDefaultEncodingName() {
+ if (defaultEncodingName == null) {
+ defaultEncodingName =
+ new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
+ }
+ return defaultEncodingName;
+ }
+
+ public String getEncodingName() {
+ String encName = options.get(Option.ENCODING);
+ if (encName == null)
+ return getDefaultEncodingName();
+ else
+ return encName;
+ }
+
+ @SuppressWarnings("cast")
+ public CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
+ String encodingName = getEncodingName();
+ CharsetDecoder decoder;
+ try {
+ decoder = getDecoder(encodingName, ignoreEncodingErrors);
+ } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
+ log.error("unsupported.encoding", encodingName);
+ return (CharBuffer)CharBuffer.allocate(1).flip();
+ }
+
+ // slightly overestimate the buffer size to avoid reallocation.
+ float factor =
+ decoder.averageCharsPerByte() * 0.8f +
+ decoder.maxCharsPerByte() * 0.2f;
+ CharBuffer dest = CharBuffer.
+ allocate(10 + (int)(inbuf.remaining()*factor));
+
+ while (true) {
+ CoderResult result = decoder.decode(inbuf, dest, true);
+ dest.flip();
+
+ if (result.isUnderflow()) { // done reading
+ // make sure there is at least one extra character
+ if (dest.limit() == dest.capacity()) {
+ dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
+ dest.flip();
+ }
+ return dest;
+ } else if (result.isOverflow()) { // buffer too small; expand
+ int newCapacity =
+ 10 + dest.capacity() +
+ (int)(inbuf.remaining()*decoder.maxCharsPerByte());
+ dest = CharBuffer.allocate(newCapacity).put(dest);
+ } else if (result.isMalformed() || result.isUnmappable()) {
+ // bad character in input
+
+ log.error(new SimpleDiagnosticPosition(dest.limit()),
+ "illegal.char.for.encoding",
+ charset == null ? encodingName : charset.name());
+
+ // skip past the coding error
+ inbuf.position(inbuf.position() + result.length());
+
+ // undo the flip() to prepare the output buffer
+ // for more translation
+ dest.position(dest.limit());
+ dest.limit(dest.capacity());
+ dest.put((char)0xfffd); // backward compatible
+ } else {
+ throw new AssertionError(result);
+ }
+ }
+ // unreached
+ }
+
+ public CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
+ Charset cs = (this.charset == null)
+ ? Charset.forName(encodingName)
+ : this.charset;
+ CharsetDecoder decoder = cs.newDecoder();
+
+ CodingErrorAction action;
+ if (ignoreEncodingErrors)
+ action = CodingErrorAction.REPLACE;
+ else
+ action = CodingErrorAction.REPORT;
+
+ return decoder
+ .onMalformedInput(action)
+ .onUnmappableCharacter(action);
+ }
+ // </editor-fold>
+
+ // <editor-fold defaultstate="collapsed" desc="ByteBuffers">
+ /**
+ * Make a byte buffer from an input stream.
+ * @param in the stream
+ * @return a byte buffer containing the contents of the stream
+ * @throws IOException if an error occurred while reading the stream
+ */
+ @SuppressWarnings("cast")
+ public ByteBuffer makeByteBuffer(InputStream in)
+ throws IOException {
+ int limit = in.available();
+ if (limit < 1024) limit = 1024;
+ ByteBuffer result = byteBufferCache.get(limit);
+ int position = 0;
+ while (in.available() != 0) {
+ if (position >= limit)
+ // expand buffer
+ result = ByteBuffer.
+ allocate(limit <<= 1).
+ put((ByteBuffer)result.flip());
+ int count = in.read(result.array(),
+ position,
+ limit - position);
+ if (count < 0) break;
+ result.position(position += count);
+ }
+ return (ByteBuffer)result.flip();
+ }
+
+ public void recycleByteBuffer(ByteBuffer bb) {
+ byteBufferCache.put(bb);
+ }
+
+ /**
+ * A single-element cache of direct byte buffers.
+ */
+ @SuppressWarnings("cast")
+ private static class ByteBufferCache {
+ private ByteBuffer cached;
+ ByteBuffer get(int capacity) {
+ if (capacity < 20480) capacity = 20480;
+ ByteBuffer result =
+ (cached != null && cached.capacity() >= capacity)
+ ? (ByteBuffer)cached.clear()
+ : ByteBuffer.allocate(capacity + capacity>>1);
+ cached = null;
+ return result;
+ }
+ void put(ByteBuffer x) {
+ cached = x;
+ }
+ }
+
+ private final ByteBufferCache byteBufferCache;
+ // </editor-fold>
+
+ // <editor-fold defaultstate="collapsed" desc="Content cache">
+ public CharBuffer getCachedContent(JavaFileObject file) {
+ ContentCacheEntry e = contentCache.get(file);
+ if (e == null)
+ return null;
+
+ if (!e.isValid(file)) {
+ contentCache.remove(file);
+ return null;
+ }
+
+ return e.getValue();
+ }
+
+ public void cache(JavaFileObject file, CharBuffer cb) {
+ contentCache.put(file, new ContentCacheEntry(file, cb));
+ }
+
+ public void flushCache(JavaFileObject file) {
+ contentCache.remove(file);
+ }
+
+ protected final Map<JavaFileObject, ContentCacheEntry> contentCache = new HashMap<>();
+
+ protected static class ContentCacheEntry {
+ final long timestamp;
+ final SoftReference<CharBuffer> ref;
+
+ ContentCacheEntry(JavaFileObject file, CharBuffer cb) {
+ this.timestamp = file.getLastModified();
+ this.ref = new SoftReference<>(cb);
+ }
+
+ boolean isValid(JavaFileObject file) {
+ return timestamp == file.getLastModified();
+ }
+
+ CharBuffer getValue() {
+ return ref.get();
+ }
+ }
+ // </editor-fold>
+
+ public static Kind getKind(Path path) {
+ return getKind(path.getFileName().toString());
+ }
+
+ public static Kind getKind(String name) {
+ if (name.endsWith(Kind.CLASS.extension))
+ return Kind.CLASS;
+ else if (name.endsWith(Kind.SOURCE.extension))
+ return Kind.SOURCE;
+ else if (name.endsWith(Kind.HTML.extension))
+ return Kind.HTML;
+ else
+ return Kind.OTHER;
+ }
+
+ protected static <T> T nullCheck(T o) {
+ return Objects.requireNonNull(o);
+ }
+
+ protected static <T> Collection<T> nullCheck(Collection<T> it) {
+ for (T t : it)
+ Objects.requireNonNull(t);
+ return it;
+ }
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileObject.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileObject.java Thu Apr 02 15:56:07 2015 -0700
@@ -38,7 +38,6 @@
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
-import com.sun.tools.javac.util.BaseFileManager;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java Thu Apr 02 15:56:07 2015 -0700
@@ -48,7 +48,6 @@
import javax.tools.FileObject;
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
-import com.sun.tools.javac.nio.PathFileObject;
import com.sun.tools.javac.util.Context;
/**
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Thu Apr 02 15:56:07 2015 -0700
@@ -63,8 +63,6 @@
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
import com.sun.tools.javac.file.RelativePath.RelativeFile;
-import com.sun.tools.javac.nio.PathFileObject;
-import com.sun.tools.javac.util.BaseFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
@@ -73,8 +71,6 @@
import static javax.tools.StandardLocation.*;
-import static com.sun.tools.javac.util.BaseFileManager.getKind;
-
/**
* This class provides access to the source, class and other files
* used by the compiler and related tools.
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Apr 02 15:56:07 2015 -0700
@@ -108,37 +108,23 @@
// Locations can use Paths.get(URI.create("jrt:"))
static final Path JRT_MARKER_FILE = Paths.get("JRT_MARKER_FILE");
- public Locations() {
+ Locations() {
initHandlers();
}
// could replace Lint by "boolean warn"
- public void update(Log log, Lint lint, FSInfo fsInfo) {
+ void update(Log log, Lint lint, FSInfo fsInfo) {
this.log = log;
warn = lint.isEnabled(Lint.LintCategory.PATH);
this.fsInfo = fsInfo;
}
- public Collection<Path> bootClassPath() {
- return getLocation(PLATFORM_CLASS_PATH);
- }
-
- public boolean isDefaultBootClassPath() {
+ boolean isDefaultBootClassPath() {
BootClassPathLocationHandler h
= (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
return h.isDefault();
}
- public Collection<Path> userClassPath() {
- return getLocation(CLASS_PATH);
- }
-
- public Collection<Path> sourcePath() {
- Collection<Path> p = getLocation(SOURCE_PATH);
- // TODO: this should be handled by the LocationHandler
- return p == null || p.isEmpty() ? null : p;
- }
-
/**
* Split a search path into its elements. Empty path elements will be ignored.
*
@@ -753,7 +739,7 @@
}
}
- public boolean handleOption(Option option, String value) {
+ boolean handleOption(Option option, String value) {
LocationHandler h = handlersForOption.get(option);
return (h == null ? false : h.handleOption(option, value));
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java Thu Apr 02 15:56:07 2015 -0700
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2009, 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.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+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.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.util.Objects;
+
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.util.DefinedBy;
+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.
+ *
+ * <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 PathFileObject implements JavaFileObject {
+ private final BaseFileManager fileManager;
+ private final Path path;
+
+ /**
+ * Create a PathFileObject within a directory, such that the binary name
+ * can be inferred from the relationship to the parent directory.
+ */
+ 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));
+ }
+ };
+ }
+
+ /**
+ * 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.
+ */
+ public static PathFileObject createJarPathFileObject(BaseFileManager fileManager,
+ final Path path) {
+ return new PathFileObject(fileManager, path) {
+ @Override
+ public String inferBinaryName(Iterable<? extends Path> paths) {
+ return toBinaryName(path);
+ }
+ };
+ }
+
+ /**
+ * 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.
+ */
+ 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 component containing the module name
+ return toBinaryName(path.subpath(1, path.getNameCount()));
+ }
+ };
+ }
+
+ /**
+ * 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, "/");
+ }
+ };
+ }
+
+ /**
+ * 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
+ }
+ }
+ }
+ return null;
+ }
+ };
+ }
+
+ protected PathFileObject(BaseFileManager fileManager, Path path) {
+ this.fileManager = Objects.requireNonNull(fileManager);
+ this.path = Objects.requireNonNull(path);
+ }
+
+ public abstract String inferBinaryName(Iterable<? extends Path> paths);
+
+ /**
+ * Return the Path for this object.
+ * @return the Path for this object.
+ */
+ public Path getPath() {
+ return path;
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
+ public Kind getKind() {
+ return BaseFileManager.getKind(path.getFileName().toString());
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
+ public boolean isNameCompatible(String simpleName, Kind kind) {
+ Objects.requireNonNull(simpleName);
+ // null check
+ 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) {
+ }
+ }
+ return false;
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
+ public NestingKind getNestingKind() {
+ return null;
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
+ public Modifier getAccessLevel() {
+ return null;
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
+ public URI toUri() {
+ 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);
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
+ public OutputStream openOutputStream() throws IOException {
+ fileManager.flushCache(this);
+ ensureParentDirectoriesExist();
+ return Files.newOutputStream(path);
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
+ public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
+ CharsetDecoder decoder = fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
+ return new InputStreamReader(openInputStream(), decoder);
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ CharBuffer cb = fileManager.getCachedContent(this);
+ if (cb == null) {
+ try (InputStream in = openInputStream()) {
+ 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(path), fileManager.getEncodingName());
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
+ public long getLastModified() {
+ try {
+ return Files.getLastModifiedTime(path).toMillis();
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
+ public boolean delete() {
+ try {
+ Files.delete(path);
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
+ public boolean isSameFile(PathFileObject other) {
+ try {
+ return Files.isSameFile(path, other.path);
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return (other instanceof PathFileObject && path.equals(((PathFileObject) other).path));
+ }
+
+ @Override
+ public int hashCode() {
+ return path.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[" + path + "]";
+ }
+
+ private void ensureParentDirectoriesExist() throws IOException {
+ Path parent = path.getParent();
+ if (parent != null)
+ Files.createDirectories(parent);
+ }
+
+ private long size() {
+ try {
+ return Files.size(path);
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+
+ protected static String toBinaryName(Path relativePath) {
+ return toBinaryName(relativePath.toString(),
+ relativePath.getFileSystem().getSeparator());
+ }
+
+ protected static String toBinaryName(String relativePath, String sep) {
+ return removeExtension(relativePath).replace(sep, ".");
+ }
+
+ protected static String removeExtension(String fileName) {
+ int lastDot = fileName.lastIndexOf(".");
+ return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
+ }
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Thu Apr 02 15:56:07 2015 -0700
@@ -42,7 +42,7 @@
import com.sun.tools.javac.jvm.Profile;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
-import com.sun.tools.javac.util.BaseFileManager;
+import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java Thu Apr 02 15:56:07 2015 -0700
@@ -39,6 +39,7 @@
import com.sun.tools.javac.api.BasicJavacTask;
import com.sun.tools.javac.file.CacheFSInfo;
+import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.processing.AnnotationProcessingError;
import com.sun.tools.javac.util.*;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java Mon Mar 30 16:38:59 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,547 +0,0 @@
-/*
- * Copyright (c) 2009, 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.nio;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-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.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.EnumSet;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-
-import javax.lang.model.SourceVersion;
-import javax.tools.FileObject;
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-import javax.tools.JavaFileObject.Kind;
-import javax.tools.StandardLocation;
-
-import com.sun.tools.javac.util.BaseFileManager;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.DefinedBy;
-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.*;
-
-import static javax.tools.StandardLocation.*;
-
-import static com.sun.tools.javac.main.Option.*;
-
-
-// NOTE the imports carefully for this compilation unit.
-//
-// Path: java.nio.file.Path -- the new NIO type for which this file manager exists
-//
-// Paths: com.sun.tools.javac.file.Paths -- legacy javac type for handling path options
-// The other Paths (java.nio.file.Paths) is not used
-
-// NOTE this and related classes depend on new API in JDK 7.
-// This requires special handling while bootstrapping the JDK build,
-// when these classes might not yet have been compiled. To workaround
-// this, the build arranges to make stubs of these classes available
-// when compiling this and related classes. The set of stub files
-// is specified in make/build.properties.
-
-/**
- * Implementation of PathFileManager: a JavaFileManager based on the use
- * of java.nio.file.Path.
- *
- * <p>Just as a Path is somewhat analagous to a File, so too is this
- * JavacPathFileManager analogous to JavacFileManager, as it relates to the
- * support of FileObjects based on File objects (i.e. just RegularFileObject,
- * not ZipFileObject and its variants.)
- *
- * <p>The default values for the standard locations supported by this file
- * manager are the same as the default values provided by JavacFileManager --
- * i.e. as determined by the javac.file.Paths class. To override these values,
- * call {@link #setLocation}.
- *
- * <p>To reduce confusion with Path objects, the locations such as "class path",
- * "source path", etc, are generically referred to here as "search paths".
- *
- * <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 JavacPathFileManager extends BaseFileManager implements PathFileManager {
- protected FileSystem defaultFileSystem;
-
- /**
- * Create a JavacPathFileManager using a given context, optionally registering
- * it as the JavaFileManager for that context.
- */
- public JavacPathFileManager(Context context, boolean register, Charset charset) {
- super(charset);
- if (register)
- context.put(JavaFileManager.class, this);
- pathsForLocation = new HashMap<>();
- fileSystems = new HashMap<>();
- setContext(context);
- }
-
- /**
- * Set the context for JavacPathFileManager.
- */
- @Override
- public void setContext(Context context) {
- super.setContext(context);
- }
-
- @Override
- public FileSystem getDefaultFileSystem() {
- if (defaultFileSystem == null)
- defaultFileSystem = FileSystems.getDefault();
- return defaultFileSystem;
- }
-
- @Override
- public void setDefaultFileSystem(FileSystem fs) {
- defaultFileSystem = fs;
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public void flush() throws IOException {
- contentCache.clear();
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public void close() throws IOException {
- for (FileSystem fs: fileSystems.values())
- fs.close();
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public ClassLoader getClassLoader(Location location) {
- nullCheck(location);
- Iterable<? extends Path> path = getLocation(location);
- if (path == null)
- return null;
- ListBuffer<URL> lb = new ListBuffer<>();
- for (Path p: path) {
- try {
- lb.append(p.toUri().toURL());
- } catch (MalformedURLException e) {
- throw new AssertionError(e);
- }
- }
-
- return getClassLoader(lb.toArray(new URL[lb.size()]));
- }
-
- // <editor-fold defaultstate="collapsed" desc="Location handling">
-
- @DefinedBy(Api.COMPILER)
- public boolean hasLocation(Location location) {
- return (getLocation(location) != null);
- }
-
- public Iterable<? extends Path> getLocation(Location location) {
- nullCheck(location);
- lazyInitSearchPaths();
- PathsForLocation path = pathsForLocation.get(location);
- if (path == null && !pathsForLocation.containsKey(location)) {
- setDefaultForLocation(location);
- path = pathsForLocation.get(location);
- }
- return path;
- }
-
- private Path getOutputLocation(Location location) {
- Iterable<? extends Path> paths = getLocation(location);
- return (paths == null ? null : paths.iterator().next());
- }
-
- public void setLocation(Location location, Iterable<? extends Path> searchPath)
- throws IOException
- {
- nullCheck(location);
- lazyInitSearchPaths();
- if (searchPath == null) {
- setDefaultForLocation(location);
- } else {
- if (location.isOutputLocation())
- checkOutputPath(searchPath);
- PathsForLocation pl = new PathsForLocation();
- for (Path p: searchPath)
- pl.add(p); // TODO -Xlint:path warn if path not found
- pathsForLocation.put(location, pl);
- }
- }
-
- private void checkOutputPath(Iterable<? extends Path> searchPath) throws IOException {
- Iterator<? extends Path> pathIter = searchPath.iterator();
- if (!pathIter.hasNext())
- throw new IllegalArgumentException("empty path for directory");
- Path path = pathIter.next();
- if (pathIter.hasNext())
- throw new IllegalArgumentException("path too long for directory");
- if (!isDirectory(path))
- throw new IOException(path + ": not a directory");
- }
-
- private void setDefaultForLocation(Location locn) {
- Collection<Path> files = null;
- if (locn instanceof StandardLocation) {
- switch ((StandardLocation) locn) {
- case CLASS_PATH:
- files = locations.userClassPath();
- break;
- case PLATFORM_CLASS_PATH:
- files = locations.bootClassPath();
- break;
- case SOURCE_PATH:
- files = locations.sourcePath();
- break;
- case CLASS_OUTPUT: {
- String arg = options.get(D);
- files = (arg == null ? null : Collections.singleton(Paths.get(arg)));
- break;
- }
- case SOURCE_OUTPUT: {
- String arg = options.get(S);
- files = (arg == null ? null : Collections.singleton(Paths.get(arg)));
- break;
- }
- }
- }
-
- PathsForLocation pl = new PathsForLocation();
- if (files != null) {
- for (Path f: files)
- pl.add(f);
- }
- if (!pl.isEmpty())
- pathsForLocation.put(locn, pl);
- }
-
- private void lazyInitSearchPaths() {
- if (!inited) {
- setDefaultForLocation(PLATFORM_CLASS_PATH);
- setDefaultForLocation(CLASS_PATH);
- setDefaultForLocation(SOURCE_PATH);
- inited = true;
- }
- }
- // where
- private boolean inited = false;
-
- private Map<Location, PathsForLocation> pathsForLocation;
-
- private static class PathsForLocation extends LinkedHashSet<Path> {
- private static final long serialVersionUID = 6788510222394486733L;
- }
-
- // </editor-fold>
-
- // <editor-fold defaultstate="collapsed" desc="FileObject handling">
-
- @Override
- public Path getPath(FileObject fo) {
- nullCheck(fo);
- if (!(fo instanceof PathFileObject))
- throw new IllegalArgumentException();
- return ((PathFileObject) fo).getPath();
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public boolean isSameFile(FileObject a, FileObject b) {
- nullCheck(a);
- nullCheck(b);
- if (!(a instanceof PathFileObject))
- throw new IllegalArgumentException("Not supported: " + a);
- if (!(b instanceof PathFileObject))
- throw new IllegalArgumentException("Not supported: " + b);
- return ((PathFileObject) a).isSameFile((PathFileObject) b);
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public Iterable<JavaFileObject> list(Location location,
- String packageName, Set<Kind> kinds, boolean recurse)
- throws IOException {
- // validatePackageName(packageName);
- nullCheck(packageName);
- nullCheck(kinds);
-
- Iterable<? extends Path> paths = getLocation(location);
- if (paths == null)
- return List.nil();
- ListBuffer<JavaFileObject> results = new ListBuffer<>();
-
- for (Path path : paths)
- list(path, packageName, kinds, recurse, results);
-
- return results.toList();
- }
-
- private void list(Path path, String packageName, final Set<Kind> kinds,
- boolean recurse, final ListBuffer<JavaFileObject> results)
- throws IOException {
- if (!Files.exists(path))
- return;
-
- final Path pathDir;
- if (isDirectory(path))
- pathDir = path;
- else {
- FileSystem fs = getFileSystem(path);
- if (fs == null)
- return;
- pathDir = fs.getRootDirectories().iterator().next();
- }
- String sep = path.getFileSystem().getSeparator();
- Path packageDir = packageName.isEmpty() ? pathDir
- : pathDir.resolve(packageName.replace(".", sep));
- if (!Files.exists(packageDir))
- return;
-
-/* Alternate impl of list, superceded by use of Files.walkFileTree */
-// Deque<Path> queue = new LinkedList<Path>();
-// queue.add(packageDir);
-//
-// Path dir;
-// while ((dir = queue.poll()) != null) {
-// DirectoryStream<Path> ds = dir.newDirectoryStream();
-// try {
-// for (Path p: ds) {
-// String name = p.getFileName().toString();
-// if (isDirectory(p)) {
-// if (recurse && SourceVersion.isIdentifier(name)) {
-// queue.add(p);
-// }
-// } else {
-// if (kinds.contains(getKind(name))) {
-// JavaFileObject fe =
-// PathFileObject.createDirectoryPathFileObject(this, p, pathDir);
-// results.append(fe);
-// }
-// }
-// }
-// } finally {
-// ds.close();
-// }
-// }
- int maxDepth = (recurse ? Integer.MAX_VALUE : 1);
- Set<FileVisitOption> opts = EnumSet.of(FOLLOW_LINKS);
- Files.walkFileTree(packageDir, opts, maxDepth,
- new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
- Path name = dir.getFileName();
- if (name == null || SourceVersion.isIdentifier(name.toString()))
- return FileVisitResult.CONTINUE;
- else
- return FileVisitResult.SKIP_SUBTREE;
- }
-
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
- if (attrs.isRegularFile() && kinds.contains(getKind(file.getFileName().toString()))) {
- // WORKAROUND for .jimage files
- if (!file.isAbsolute())
- file = pathDir.resolve(file);
- JavaFileObject fe =
- PathFileObject.createDirectoryPathFileObject(
- JavacPathFileManager.this, file, pathDir);
- results.append(fe);
- }
- return FileVisitResult.CONTINUE;
- }
- });
- }
-
- @Override
- public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
- Iterable<? extends Path> paths) {
- ArrayList<PathFileObject> result;
- if (paths instanceof Collection<?>)
- result = new ArrayList<>(((Collection<?>)paths).size());
- else
- result = new ArrayList<>();
- for (Path p: paths)
- result.add(PathFileObject.createSimplePathFileObject(this, nullCheck(p)));
- return result;
- }
-
- @Override
- public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) {
- return getJavaFileObjectsFromPaths(Arrays.asList(nullCheck(paths)));
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public JavaFileObject getJavaFileForInput(Location location,
- String className, Kind kind) throws IOException {
- return getFileForInput(location, getRelativePath(className, kind));
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public FileObject getFileForInput(Location location,
- String packageName, String relativeName) throws IOException {
- return getFileForInput(location, getRelativePath(packageName, relativeName));
- }
-
- private JavaFileObject getFileForInput(Location location, String relativePath)
- throws IOException {
- for (Path p: getLocation(location)) {
- if (isDirectory(p)) {
- Path f = resolve(p, relativePath);
- if (Files.exists(f))
- return PathFileObject.createDirectoryPathFileObject(this, f, p);
- } else {
- FileSystem fs = getFileSystem(p);
- if (fs != null) {
- Path file = getPath(fs, relativePath);
- if (Files.exists(file))
- return PathFileObject.createJarPathFileObject(this, file);
- }
- }
- }
- return null;
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public JavaFileObject getJavaFileForOutput(Location location,
- String className, Kind kind, FileObject sibling) throws IOException {
- return getFileForOutput(location, getRelativePath(className, kind), sibling);
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public FileObject getFileForOutput(Location location, String packageName,
- String relativeName, FileObject sibling)
- throws IOException {
- return getFileForOutput(location, getRelativePath(packageName, relativeName), sibling);
- }
-
- private JavaFileObject getFileForOutput(Location location,
- String relativePath, FileObject sibling) {
- Path dir = getOutputLocation(location);
- if (dir == null) {
- if (location == CLASS_OUTPUT) {
- Path siblingDir = null;
- if (sibling != null && sibling instanceof PathFileObject) {
- siblingDir = ((PathFileObject) sibling).getPath().getParent();
- }
- return PathFileObject.createSiblingPathFileObject(this,
- siblingDir.resolve(getBaseName(relativePath)),
- relativePath);
- } else if (location == SOURCE_OUTPUT) {
- dir = getOutputLocation(CLASS_OUTPUT);
- }
- }
-
- Path file;
- if (dir != null) {
- file = resolve(dir, relativePath);
- return PathFileObject.createDirectoryPathFileObject(this, file, dir);
- } else {
- file = getPath(getDefaultFileSystem(), relativePath);
- return PathFileObject.createSimplePathFileObject(this, file);
- }
-
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public String inferBinaryName(Location location, JavaFileObject fo) {
- nullCheck(fo);
- // Need to match the path semantics of list(location, ...)
- Iterable<? extends Path> paths = getLocation(location);
- if (paths == null) {
- return null;
- }
-
- if (!(fo instanceof PathFileObject))
- throw new IllegalArgumentException(fo.getClass().getName());
-
- return ((PathFileObject) fo).inferBinaryName(paths);
- }
-
- private FileSystem getFileSystem(Path p) throws IOException {
- FileSystem fs = fileSystems.get(p);
- if (fs == null) {
- fs = FileSystems.newFileSystem(p, null);
- fileSystems.put(p, fs);
- }
- return fs;
- }
-
- private Map<Path,FileSystem> fileSystems;
-
- // </editor-fold>
-
- // <editor-fold defaultstate="collapsed" desc="Utility methods">
-
- private static String getRelativePath(String className, Kind kind) {
- return className.replace(".", "/") + kind.extension;
- }
-
- private static String getRelativePath(String packageName, String relativeName) {
- return packageName.isEmpty()
- ? relativeName : packageName.replace(".", "/") + "/" + relativeName;
- }
-
- private static String getBaseName(String relativePath) {
- int lastSep = relativePath.lastIndexOf("/");
- return relativePath.substring(lastSep + 1); // safe if "/" not found
- }
-
- private static boolean isDirectory(Path path) throws IOException {
- BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
- return attrs.isDirectory();
- }
-
- private static Path getPath(FileSystem fs, String relativePath) {
- return fs.getPath(relativePath.replace("/", fs.getSeparator()));
- }
-
- private static Path resolve(Path base, String relativePath) {
- FileSystem fs = base.getFileSystem();
- Path rp = fs.getPath(relativePath.replace("/", fs.getSeparator()));
- return base.resolve(rp);
- }
-
- // </editor-fold>
-
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/nio/PathFileManager.java Mon Mar 30 16:38:59 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, 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.nio;
-
-import java.io.IOException;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Path;
-import javax.tools.FileObject;
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-
-/**
- * File manager based on {@link java.nio.file.Path}.
- *
- * Eventually, this should be moved to javax.tools.
- * Also, JavaCompiler might reasonably provide a method getPathFileManager,
- * similar to {@link javax.tools.JavaCompiler#getStandardFileManager
- * getStandardFileManager}. However, would need to be handled carefully
- * as another forward reference from langtools to jdk.
- *
- * <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 interface PathFileManager extends JavaFileManager {
- /**
- * Get the default file system used to create paths. If no value has been
- * set, the default file system is {@link FileSystems#getDefault}.
- */
- FileSystem getDefaultFileSystem();
-
- /**
- * Set the default file system used to create paths.
- * @param fs the default file system used to create any new paths.
- */
- void setDefaultFileSystem(FileSystem fs);
-
- /**
- * Get file objects representing the given files.
- *
- * @param paths a list of paths
- * @return a list of file objects
- * @throws IllegalArgumentException if the list of paths includes
- * a directory
- */
- Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
- Iterable<? extends Path> paths);
-
- /**
- * Get file objects representing the given paths.
- * Convenience method equivalent to:
- *
- * <pre>
- * getJavaFileObjectsFromPaths({@linkplain java.util.Arrays#asList Arrays.asList}(paths))
- * </pre>
- *
- * @param paths an array of paths
- * @return a list of file objects
- * @throws IllegalArgumentException if the array of files includes
- * a directory
- * @throws NullPointerException if the given array contains null
- * elements
- */
- Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths);
-
- /**
- * Return the Path for a file object that has been obtained from this
- * file manager.
- *
- * @param fo A file object that has been obtained from this file manager.
- * @return The underlying Path object.
- * @throws IllegalArgumentException is the file object was not obtained from
- * from this file manager.
- */
- Path getPath(FileObject fo);
-
- /**
- * Get the search path associated with the given location.
- *
- * @param location a location
- * @return a list of paths or {@code null} if this location has no
- * associated search path
- * @see #setLocation
- */
- Iterable<? extends Path> getLocation(Location location);
-
- /**
- * Associate the given search path with the given location. Any
- * previous value will be discarded.
- *
- * @param location a location
- * @param searchPath a list of files, if {@code null} use the default
- * search path for this location
- * @see #getLocation
- * @throws IllegalArgumentException if location is an output
- * location and searchpath does not contain exactly one element
- * @throws IOException if location is an output location and searchpath
- * does not represent an existing directory
- */
- void setLocation(Location location, Iterable<? extends Path> searchPath) throws IOException;
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/nio/PathFileObject.java Mon Mar 30 16:38:59 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-/*
- * Copyright (c) 2009, 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.nio;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-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.Files;
-import java.nio.file.LinkOption;
-import java.nio.file.Path;
-import java.util.Objects;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.NestingKind;
-import javax.tools.JavaFileObject;
-
-import com.sun.tools.javac.util.BaseFileManager;
-import com.sun.tools.javac.util.DefinedBy;
-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.
- *
- * <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 PathFileObject implements JavaFileObject {
- private final BaseFileManager fileManager;
- private final Path path;
-
- /**
- * Create a PathFileObject within a directory, such that the binary name
- * can be inferred from the relationship to the parent directory.
- */
- 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));
- }
- };
- }
-
- /**
- * 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.
- */
- public static PathFileObject createJarPathFileObject(BaseFileManager fileManager,
- final Path path) {
- return new PathFileObject(fileManager, path) {
- @Override
- public String inferBinaryName(Iterable<? extends Path> paths) {
- return toBinaryName(path);
- }
- };
- }
-
- /**
- * 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.
- */
- 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 component containing the module name
- return toBinaryName(path.subpath(1, path.getNameCount()));
- }
- };
- }
-
- /**
- * 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, "/");
- }
- };
- }
-
- /**
- * 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
- }
- }
- }
- return null;
- }
- };
- }
-
- protected PathFileObject(BaseFileManager fileManager, Path path) {
- this.fileManager = Objects.requireNonNull(fileManager);
- this.path = Objects.requireNonNull(path);
- }
-
- public abstract String inferBinaryName(Iterable<? extends Path> paths);
-
- /**
- * Return the Path for this object.
- * @return the Path for this object.
- */
- public Path getPath() {
- return path;
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public Kind getKind() {
- return BaseFileManager.getKind(path.getFileName().toString());
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public boolean isNameCompatible(String simpleName, Kind kind) {
- Objects.requireNonNull(simpleName);
- // null check
- 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) {
- }
- }
- return false;
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public NestingKind getNestingKind() {
- return null;
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public Modifier getAccessLevel() {
- return null;
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public URI toUri() {
- 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);
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public OutputStream openOutputStream() throws IOException {
- fileManager.flushCache(this);
- ensureParentDirectoriesExist();
- return Files.newOutputStream(path);
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
- CharsetDecoder decoder = fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
- return new InputStreamReader(openInputStream(), decoder);
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
- CharBuffer cb = fileManager.getCachedContent(this);
- if (cb == null) {
- try (InputStream in = openInputStream()) {
- 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(path), fileManager.getEncodingName());
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public long getLastModified() {
- try {
- return Files.getLastModifiedTime(path).toMillis();
- } catch (IOException e) {
- return -1;
- }
- }
-
- @Override @DefinedBy(Api.COMPILER)
- public boolean delete() {
- try {
- Files.delete(path);
- return true;
- } catch (IOException e) {
- return false;
- }
- }
-
- public boolean isSameFile(PathFileObject other) {
- try {
- return Files.isSameFile(path, other.path);
- } catch (IOException e) {
- return false;
- }
- }
-
- @Override
- public boolean equals(Object other) {
- return (other instanceof PathFileObject && path.equals(((PathFileObject) other).path));
- }
-
- @Override
- public int hashCode() {
- return path.hashCode();
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + "[" + path + "]";
- }
-
- private void ensureParentDirectoriesExist() throws IOException {
- Path parent = path.getParent();
- if (parent != null)
- Files.createDirectories(parent);
- }
-
- private long size() {
- try {
- return Files.size(path);
- } catch (IOException e) {
- return -1;
- }
- }
-
- protected static String toBinaryName(Path relativePath) {
- return toBinaryName(relativePath.toString(),
- relativePath.getFileSystem().getSeparator());
- }
-
- protected static String toBinaryName(String relativePath, String sep) {
- return removeExtension(relativePath).replace(sep, ".");
- }
-
- protected static String removeExtension(String fileName) {
- int lastDot = fileName.lastIndexOf(".");
- return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
- }
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/BaseFileManager.java Mon Mar 30 16:38:59 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,443 +0,0 @@
-/*
- * Copyright (c) 2009, 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.util;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.lang.ref.SoftReference;
-import java.lang.reflect.Constructor;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-import java.nio.file.Path;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-import javax.tools.JavaFileObject.Kind;
-
-import com.sun.tools.javac.code.Lint;
-import com.sun.tools.javac.code.Source;
-import com.sun.tools.javac.file.FSInfo;
-import com.sun.tools.javac.file.Locations;
-import com.sun.tools.javac.main.Option;
-import com.sun.tools.javac.main.OptionHelper;
-import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
-import com.sun.tools.javac.util.DefinedBy.Api;
-import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
-
-/**
- * Utility methods for building a filemanager.
- * There are no references here to file-system specific objects such as
- * java.io.File or java.nio.file.Path.
- */
-public abstract class BaseFileManager implements JavaFileManager {
- protected BaseFileManager(Charset charset) {
- this.charset = charset;
- byteBufferCache = new ByteBufferCache();
- locations = createLocations();
- }
-
- /**
- * Set the context for JavacPathFileManager.
- * @param context the context containing items to be associated with the file manager
- */
- public void setContext(Context context) {
- log = Log.instance(context);
- options = Options.instance(context);
- classLoaderClass = options.get("procloader");
- locations.update(log, Lint.instance(context), FSInfo.instance(context));
- }
-
- protected Locations createLocations() {
- return new Locations();
- }
-
- /**
- * The log to be used for error reporting.
- */
- public Log log;
-
- /**
- * User provided charset (through javax.tools).
- */
- protected Charset charset;
-
- protected Options options;
-
- protected String classLoaderClass;
-
- protected Locations locations;
-
- /**
- * A flag for clients to use to indicate that this file manager should
- * be closed when it is no longer required.
- */
- public boolean autoClose;
-
- protected Source getSource() {
- String sourceName = options.get(Option.SOURCE);
- Source source = null;
- if (sourceName != null)
- source = Source.lookup(sourceName);
- return (source != null ? source : Source.DEFAULT);
- }
-
- protected ClassLoader getClassLoader(URL[] urls) {
- ClassLoader thisClassLoader = getClass().getClassLoader();
-
- // Allow the following to specify a closeable classloader
- // other than URLClassLoader.
-
- // 1: Allow client to specify the class to use via hidden option
- if (classLoaderClass != null) {
- try {
- Class<? extends ClassLoader> loader =
- Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
- Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
- Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
- return constr.newInstance(urls, thisClassLoader);
- } catch (ReflectiveOperationException t) {
- // ignore errors loading user-provided class loader, fall through
- }
- }
- return new URLClassLoader(urls, thisClassLoader);
- }
-
- public boolean isDefaultBootClassPath() {
- return locations.isDefaultBootClassPath();
- }
-
- // <editor-fold defaultstate="collapsed" desc="Option handling">
- @Override @DefinedBy(Api.COMPILER)
- public boolean handleOption(String current, Iterator<String> remaining) {
- OptionHelper helper = new GrumpyHelper(log) {
- @Override
- public String get(Option option) {
- return options.get(option.getText());
- }
-
- @Override
- public void put(String name, String value) {
- options.put(name, value);
- }
-
- @Override
- public void remove(String name) {
- options.remove(name);
- }
-
- @Override
- public boolean handleFileManagerOption(Option option, String value) {
- return handleOption(option, value);
- }
- };
-
- for (Option o: javacFileManagerOptions) {
- if (o.matches(current)) {
- if (o.hasArg()) {
- if (remaining.hasNext()) {
- if (!o.process(helper, current, remaining.next()))
- return true;
- }
- } else {
- if (!o.process(helper, current))
- return true;
- }
- // operand missing, or process returned true
- throw new IllegalArgumentException(current);
- }
- }
-
- return false;
- }
- // where
- private static final Set<Option> javacFileManagerOptions =
- Option.getJavacFileManagerOptions();
-
- @Override @DefinedBy(Api.COMPILER)
- public int isSupportedOption(String option) {
- for (Option o : javacFileManagerOptions) {
- if (o.matches(option))
- return o.hasArg() ? 1 : 0;
- }
- return -1;
- }
-
- /**
- * Common back end for OptionHelper handleFileManagerOption.
- * @param option the option whose value to be set
- * @param value the value for the option
- * @return true if successful, and false otherwise
- */
- public boolean handleOption(Option option, String value) {
- return locations.handleOption(option, value);
- }
-
- /**
- * Call handleOption for collection of options and corresponding values.
- * @param map a collection of options and corresponding values
- * @return true if all the calls are successful
- */
- public boolean handleOptions(Map<Option, String> map) {
- boolean ok = true;
- for (Map.Entry<Option, String> e: map.entrySet())
- ok = ok & handleOption(e.getKey(), e.getValue());
- return ok;
- }
-
- // </editor-fold>
-
- // <editor-fold defaultstate="collapsed" desc="Encoding">
- private String defaultEncodingName;
- private String getDefaultEncodingName() {
- if (defaultEncodingName == null) {
- defaultEncodingName =
- new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
- }
- return defaultEncodingName;
- }
-
- public String getEncodingName() {
- String encName = options.get(Option.ENCODING);
- if (encName == null)
- return getDefaultEncodingName();
- else
- return encName;
- }
-
- @SuppressWarnings("cast")
- public CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
- String encodingName = getEncodingName();
- CharsetDecoder decoder;
- try {
- decoder = getDecoder(encodingName, ignoreEncodingErrors);
- } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
- log.error("unsupported.encoding", encodingName);
- return (CharBuffer)CharBuffer.allocate(1).flip();
- }
-
- // slightly overestimate the buffer size to avoid reallocation.
- float factor =
- decoder.averageCharsPerByte() * 0.8f +
- decoder.maxCharsPerByte() * 0.2f;
- CharBuffer dest = CharBuffer.
- allocate(10 + (int)(inbuf.remaining()*factor));
-
- while (true) {
- CoderResult result = decoder.decode(inbuf, dest, true);
- dest.flip();
-
- if (result.isUnderflow()) { // done reading
- // make sure there is at least one extra character
- if (dest.limit() == dest.capacity()) {
- dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
- dest.flip();
- }
- return dest;
- } else if (result.isOverflow()) { // buffer too small; expand
- int newCapacity =
- 10 + dest.capacity() +
- (int)(inbuf.remaining()*decoder.maxCharsPerByte());
- dest = CharBuffer.allocate(newCapacity).put(dest);
- } else if (result.isMalformed() || result.isUnmappable()) {
- // bad character in input
-
- log.error(new SimpleDiagnosticPosition(dest.limit()),
- "illegal.char.for.encoding",
- charset == null ? encodingName : charset.name());
-
- // skip past the coding error
- inbuf.position(inbuf.position() + result.length());
-
- // undo the flip() to prepare the output buffer
- // for more translation
- dest.position(dest.limit());
- dest.limit(dest.capacity());
- dest.put((char)0xfffd); // backward compatible
- } else {
- throw new AssertionError(result);
- }
- }
- // unreached
- }
-
- public CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
- Charset cs = (this.charset == null)
- ? Charset.forName(encodingName)
- : this.charset;
- CharsetDecoder decoder = cs.newDecoder();
-
- CodingErrorAction action;
- if (ignoreEncodingErrors)
- action = CodingErrorAction.REPLACE;
- else
- action = CodingErrorAction.REPORT;
-
- return decoder
- .onMalformedInput(action)
- .onUnmappableCharacter(action);
- }
- // </editor-fold>
-
- // <editor-fold defaultstate="collapsed" desc="ByteBuffers">
- /**
- * Make a byte buffer from an input stream.
- * @param in the stream
- * @return a byte buffer containing the contents of the stream
- * @throws IOException if an error occurred while reading the stream
- */
- @SuppressWarnings("cast")
- public ByteBuffer makeByteBuffer(InputStream in)
- throws IOException {
- int limit = in.available();
- if (limit < 1024) limit = 1024;
- ByteBuffer result = byteBufferCache.get(limit);
- int position = 0;
- while (in.available() != 0) {
- if (position >= limit)
- // expand buffer
- result = ByteBuffer.
- allocate(limit <<= 1).
- put((ByteBuffer)result.flip());
- int count = in.read(result.array(),
- position,
- limit - position);
- if (count < 0) break;
- result.position(position += count);
- }
- return (ByteBuffer)result.flip();
- }
-
- public void recycleByteBuffer(ByteBuffer bb) {
- byteBufferCache.put(bb);
- }
-
- /**
- * A single-element cache of direct byte buffers.
- */
- @SuppressWarnings("cast")
- private static class ByteBufferCache {
- private ByteBuffer cached;
- ByteBuffer get(int capacity) {
- if (capacity < 20480) capacity = 20480;
- ByteBuffer result =
- (cached != null && cached.capacity() >= capacity)
- ? (ByteBuffer)cached.clear()
- : ByteBuffer.allocate(capacity + capacity>>1);
- cached = null;
- return result;
- }
- void put(ByteBuffer x) {
- cached = x;
- }
- }
-
- private final ByteBufferCache byteBufferCache;
- // </editor-fold>
-
- // <editor-fold defaultstate="collapsed" desc="Content cache">
- public CharBuffer getCachedContent(JavaFileObject file) {
- ContentCacheEntry e = contentCache.get(file);
- if (e == null)
- return null;
-
- if (!e.isValid(file)) {
- contentCache.remove(file);
- return null;
- }
-
- return e.getValue();
- }
-
- public void cache(JavaFileObject file, CharBuffer cb) {
- contentCache.put(file, new ContentCacheEntry(file, cb));
- }
-
- public void flushCache(JavaFileObject file) {
- contentCache.remove(file);
- }
-
- protected final Map<JavaFileObject, ContentCacheEntry> contentCache = new HashMap<>();
-
- protected static class ContentCacheEntry {
- final long timestamp;
- final SoftReference<CharBuffer> ref;
-
- ContentCacheEntry(JavaFileObject file, CharBuffer cb) {
- this.timestamp = file.getLastModified();
- this.ref = new SoftReference<>(cb);
- }
-
- boolean isValid(JavaFileObject file) {
- return timestamp == file.getLastModified();
- }
-
- CharBuffer getValue() {
- return ref.get();
- }
- }
- // </editor-fold>
-
- public static Kind getKind(Path path) {
- return getKind(path.getFileName().toString());
- }
-
- public static Kind getKind(String name) {
- if (name.endsWith(Kind.CLASS.extension))
- return Kind.CLASS;
- else if (name.endsWith(Kind.SOURCE.extension))
- return Kind.SOURCE;
- else if (name.endsWith(Kind.HTML.extension))
- return Kind.HTML;
- else
- return Kind.OTHER;
- }
-
- protected static <T> T nullCheck(T o) {
- return Objects.requireNonNull(o);
- }
-
- protected static <T> Collection<T> nullCheck(Collection<T> it) {
- for (T t : it)
- Objects.requireNonNull(t);
- return it;
- }
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java Thu Apr 02 15:56:07 2015 -0700
@@ -56,17 +56,10 @@
DocFileFactory f = factories.get(configuration);
if (f == null) {
JavaFileManager fm = configuration.getFileManager();
- if (fm instanceof StandardJavaFileManager)
+ if (fm instanceof StandardJavaFileManager) {
f = new StandardDocFileFactory(configuration);
- else {
- try {
- Class<?> pathFileManagerClass =
- Class.forName("com.sun.tools.javac.nio.PathFileManager");
- if (pathFileManagerClass.isAssignableFrom(fm.getClass()))
- f = new PathDocFileFactory(configuration);
- } catch (Throwable t) {
- throw new IllegalStateException(t);
- }
+ } else {
+ throw new IllegalStateException();
}
factories.put(configuration, f);
}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/PathDocFileFactory.java Mon Mar 30 16:38:59 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,320 +0,0 @@
-/*
- * Copyright (c) 1998, 2013, 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.doclets.internal.toolkit.util;
-
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.tools.DocumentationTool;
-import javax.tools.FileObject;
-import javax.tools.JavaFileManager.Location;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardLocation;
-
-import com.sun.tools.doclets.internal.toolkit.Configuration;
-import com.sun.tools.javac.nio.PathFileManager;
-
-
-/**
- * Implementation of DocFileFactory using a {@link PathFileManager}.
- *
- * <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>
- *
- * @since 1.8
- */
-class PathDocFileFactory extends DocFileFactory {
- private final PathFileManager fileManager;
- private final Path destDir;
-
- public PathDocFileFactory(Configuration configuration) {
- super(configuration);
- fileManager = (PathFileManager) configuration.getFileManager();
-
- if (!configuration.destDirName.isEmpty()
- || !fileManager.hasLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT)) {
- try {
- String dirName = configuration.destDirName.isEmpty() ? "." : configuration.destDirName;
- Path dir = fileManager.getDefaultFileSystem().getPath(dirName);
- fileManager.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(dir));
- } catch (IOException e) {
- throw new DocletAbortException(e);
- }
- }
-
- destDir = fileManager.getLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT).iterator().next();
- }
-
- public DocFile createFileForDirectory(String file) {
- return new StandardDocFile(fileManager.getDefaultFileSystem().getPath(file));
- }
-
- public DocFile createFileForInput(String file) {
- return new StandardDocFile(fileManager.getDefaultFileSystem().getPath(file));
- }
-
- public DocFile createFileForOutput(DocPath path) {
- return new StandardDocFile(DocumentationTool.Location.DOCUMENTATION_OUTPUT, path);
- }
-
- @Override
- Iterable<DocFile> list(Location location, DocPath path) {
- if (location != StandardLocation.SOURCE_PATH)
- throw new IllegalArgumentException();
-
- Set<DocFile> files = new LinkedHashSet<>();
- if (fileManager.hasLocation(location)) {
- for (Path f: fileManager.getLocation(location)) {
- if (Files.isDirectory(f)) {
- f = f.resolve(path.getPath());
- if (Files.exists(f))
- files.add(new StandardDocFile(f));
- }
- }
- }
- return files;
- }
-
- class StandardDocFile extends DocFile {
- private Path file;
-
- /** Create a StandardDocFile for a given file. */
- private StandardDocFile(Path file) {
- super(configuration);
- this.file = file;
- }
-
- /** Create a StandardDocFile for a given location and relative path. */
- private StandardDocFile(Location location, DocPath path) {
- super(configuration, location, path);
- this.file = destDir.resolve(path.getPath());
- }
-
- /** Open an input stream for the file. */
- public InputStream openInputStream() throws IOException {
- JavaFileObject fo = getJavaFileObjectForInput(file);
- return new BufferedInputStream(fo.openInputStream());
- }
-
- /**
- * Open an output stream for the file.
- * The file must have been created with a location of
- * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
- */
- public OutputStream openOutputStream() throws IOException, UnsupportedEncodingException {
- if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
- throw new IllegalStateException();
-
- OutputStream out = getFileObjectForOutput(path).openOutputStream();
- return new BufferedOutputStream(out);
- }
-
- /**
- * Open an writer for the file, using the encoding (if any) given in the
- * doclet configuration.
- * The file must have been created with a location of
- * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
- */
- public Writer openWriter() throws IOException, UnsupportedEncodingException {
- if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
- throw new IllegalStateException();
-
- OutputStream out = getFileObjectForOutput(path).openOutputStream();
- if (configuration.docencoding == null) {
- return new BufferedWriter(new OutputStreamWriter(out));
- } else {
- return new BufferedWriter(new OutputStreamWriter(out, configuration.docencoding));
- }
- }
-
- /** Return true if the file can be read. */
- public boolean canRead() {
- return Files.isReadable(file);
- }
-
- /** Return true if the file can be written. */
- public boolean canWrite() {
- return Files.isWritable(file);
- }
-
- /** Return true if the file exists. */
- public boolean exists() {
- return Files.exists(file);
- }
-
- /** Return the base name (last component) of the file name. */
- public String getName() {
- return file.getFileName().toString();
- }
-
- /** Return the file system path for this file. */
- public String getPath() {
- return file.toString();
- }
-
- /** Return true is file has an absolute path name. */
- public boolean isAbsolute() {
- return file.isAbsolute();
- }
-
- /** Return true is file identifies a directory. */
- public boolean isDirectory() {
- return Files.isDirectory(file);
- }
-
- /** Return true is file identifies a file. */
- public boolean isFile() {
- return Files.isRegularFile(file);
- }
-
- /** Return true if this file is the same as another. */
- public boolean isSameFile(DocFile other) {
- if (!(other instanceof StandardDocFile))
- return false;
-
- try {
- return Files.isSameFile(file, ((StandardDocFile) other).file);
- } catch (IOException e) {
- return false;
- }
- }
-
- /** If the file is a directory, list its contents. */
- public Iterable<DocFile> list() throws IOException {
- List<DocFile> files = new ArrayList<>();
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(file)) {
- for (Path f: ds) {
- files.add(new StandardDocFile(f));
- }
- }
- return files;
- }
-
- /** Create the file as a directory, including any parent directories. */
- public boolean mkdirs() {
- try {
- Files.createDirectories(file);
- return true;
- } catch (IOException e) {
- return false;
- }
- }
-
- /**
- * Derive a new file by resolving a relative path against this file.
- * The new file will inherit the configuration and location of this file
- * If this file has a path set, the new file will have a corresponding
- * new path.
- */
- public DocFile resolve(DocPath p) {
- return resolve(p.getPath());
- }
-
- /**
- * Derive a new file by resolving a relative path against this file.
- * The new file will inherit the configuration and location of this file
- * If this file has a path set, the new file will have a corresponding
- * new path.
- */
- public DocFile resolve(String p) {
- if (location == null && path == null) {
- return new StandardDocFile(file.resolve(p));
- } else {
- return new StandardDocFile(location, path.resolve(p));
- }
- }
-
- /**
- * Resolve a relative file against the given output location.
- * @param locn Currently, only
- * {@link DocumentationTool.Location.DOCUMENTATION_OUTPUT} is supported.
- */
- public DocFile resolveAgainst(Location locn) {
- if (locn != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
- throw new IllegalArgumentException();
- return new StandardDocFile(destDir.resolve(file));
- }
-
- /** Return a string to identify the contents of this object,
- * for debugging purposes.
- */
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("PathDocFile[");
- if (location != null)
- sb.append("locn:").append(location).append(",");
- if (path != null)
- sb.append("path:").append(path.getPath()).append(",");
- sb.append("file:").append(file);
- sb.append("]");
- return sb.toString();
- }
-
- private JavaFileObject getJavaFileObjectForInput(Path file) {
- return fileManager.getJavaFileObjects(file).iterator().next();
- }
-
- private FileObject getFileObjectForOutput(DocPath path) throws IOException {
- // break the path into a package-part and the rest, by finding
- // the position of the last '/' before an invalid character for a
- // package name, such as the "." before an extension or the "-"
- // in filenames like package-summary.html, doc-files or src-html.
- String p = path.getPath();
- int lastSep = -1;
- for (int i = 0; i < p.length(); i++) {
- char ch = p.charAt(i);
- if (ch == '/') {
- lastSep = i;
- } else if (i == lastSep + 1 && !Character.isJavaIdentifierStart(ch)
- || !Character.isJavaIdentifierPart(ch)) {
- break;
- }
- }
- String pkg = (lastSep == -1) ? "" : p.substring(0, lastSep);
- String rest = p.substring(lastSep + 1);
- return fileManager.getFileForOutput(location, pkg, rest, null);
- }
- }
-
-}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java Thu Apr 02 15:56:07 2015 -0700
@@ -42,7 +42,7 @@
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.CommandLine;
import com.sun.tools.javac.main.Option;
-import com.sun.tools.javac.util.BaseFileManager;
+import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/api/JavadocTool.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/api/JavadocTool.java Thu Apr 02 15:56:07 2015 -0700
@@ -46,7 +46,7 @@
import com.sun.tools.javac.api.ClientCodeWrapper;
import com.sun.tools.javac.file.JavacFileManager;
-import com.sun.tools.javac.util.BaseFileManager;
+import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DefinedBy;
--- a/langtools/test/tools/javadoc/api/basic/GetTask_FileManagerTest.java Mon Mar 30 16:38:59 2015 +0100
+++ b/langtools/test/tools/javadoc/api/basic/GetTask_FileManagerTest.java Thu Apr 02 15:56:07 2015 -0700
@@ -45,8 +45,6 @@
import javax.tools.ToolProvider;
import com.sun.tools.javac.file.JavacFileManager;
-import com.sun.tools.javac.nio.JavacPathFileManager;
-import com.sun.tools.javac.nio.PathFileManager;
import com.sun.tools.javac.util.Context;
/**
@@ -59,7 +57,7 @@
/**
* Verify that an alternate file manager can be specified:
- * in this case, a PathFileManager.
+ * in this case, a TestFileManager.
*/
@Test
public void testFileManager() throws Exception {