feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
128
jdkSrc/jdk8/com/sun/tools/javac/file/BaseFileObject.java
Normal file
128
jdkSrc/jdk8/com/sun/tools/javac/file/BaseFileObject.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2009, 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.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 javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.NestingKind;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import static javax.tools.JavaFileObject.Kind.*;
|
||||
|
||||
import com.sun.tools.javac.util.BaseFileManager;
|
||||
|
||||
/**
|
||||
* <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() + "]";
|
||||
}
|
||||
|
||||
public NestingKind getNestingKind() { return null; }
|
||||
|
||||
public Modifier getAccessLevel() { return null; }
|
||||
|
||||
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 File> 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(File 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;
|
||||
}
|
||||
124
jdkSrc/jdk8/com/sun/tools/javac/file/CacheFSInfo.java
Normal file
124
jdkSrc/jdk8/com/sun/tools/javac/file/CacheFSInfo.java
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2011, 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.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.sun.tools.javac.util.Context;
|
||||
|
||||
/**
|
||||
* Caching implementation of FSInfo.
|
||||
*
|
||||
* <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 CacheFSInfo extends FSInfo {
|
||||
|
||||
/**
|
||||
* Register a Context.Factory to create a CacheFSInfo.
|
||||
*/
|
||||
public static void preRegister(Context context) {
|
||||
context.put(FSInfo.class, new Context.Factory<FSInfo>() {
|
||||
public FSInfo make(Context c) {
|
||||
FSInfo instance = new CacheFSInfo();
|
||||
c.put(FSInfo.class, instance);
|
||||
return instance;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getCanonicalFile(File file) {
|
||||
Entry e = getEntry(file);
|
||||
return e.canonicalFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(File file) {
|
||||
Entry e = getEntry(file);
|
||||
return e.exists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory(File file) {
|
||||
Entry e = getEntry(file);
|
||||
return e.isDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFile(File file) {
|
||||
Entry e = getEntry(file);
|
||||
return e.isFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<File> getJarClassPath(File file) throws IOException {
|
||||
// don't bother to lock the cache, because it is thread-safe, and
|
||||
// because the worst that can happen would be to create two identical
|
||||
// jar class paths together and have one overwrite the other.
|
||||
Entry e = getEntry(file);
|
||||
if (e.jarClassPath == null)
|
||||
e.jarClassPath = super.getJarClassPath(file);
|
||||
return e.jarClassPath;
|
||||
}
|
||||
|
||||
private Entry getEntry(File file) {
|
||||
// don't bother to lock the cache, because it is thread-safe, and
|
||||
// because the worst that can happen would be to create two identical
|
||||
// entries together and have one overwrite the other.
|
||||
Entry e = cache.get(file);
|
||||
if (e == null) {
|
||||
e = new Entry();
|
||||
e.canonicalFile = super.getCanonicalFile(file);
|
||||
e.exists = super.exists(file);
|
||||
e.isDirectory = super.isDirectory(file);
|
||||
e.isFile = super.isFile(file);
|
||||
cache.put(file, e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
// could also be a Map<File,SoftReference<Entry>> ?
|
||||
private Map<File,Entry> cache = new ConcurrentHashMap<File,Entry>();
|
||||
|
||||
private static class Entry {
|
||||
File canonicalFile;
|
||||
boolean exists;
|
||||
boolean isFile;
|
||||
boolean isDirectory;
|
||||
List<File> jarClassPath;
|
||||
}
|
||||
}
|
||||
94
jdkSrc/jdk8/com/sun/tools/javac/file/FSInfo.java
Normal file
94
jdkSrc/jdk8/com/sun/tools/javac/file/FSInfo.java
Normal file
@@ -0,0 +1,94 @@
|
||||
|
||||
package com.sun.tools.javac.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import com.sun.tools.javac.util.Context;
|
||||
|
||||
/**
|
||||
* Get meta-info about files. Default direct (non-caching) implementation.
|
||||
* @see CacheFSInfo
|
||||
*
|
||||
* <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 FSInfo {
|
||||
|
||||
/** Get the FSInfo instance for this context.
|
||||
* @param context the context
|
||||
* @return the Paths instance for this context
|
||||
*/
|
||||
public static FSInfo instance(Context context) {
|
||||
FSInfo instance = context.get(FSInfo.class);
|
||||
if (instance == null)
|
||||
instance = new FSInfo();
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected FSInfo() {
|
||||
}
|
||||
|
||||
protected FSInfo(Context context) {
|
||||
context.put(FSInfo.class, this);
|
||||
}
|
||||
|
||||
public File getCanonicalFile(File file) {
|
||||
try {
|
||||
return file.getCanonicalFile();
|
||||
} catch (IOException e) {
|
||||
return file.getAbsoluteFile();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean exists(File file) {
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
public boolean isDirectory(File file) {
|
||||
return file.isDirectory();
|
||||
}
|
||||
|
||||
public boolean isFile(File file) {
|
||||
return file.isFile();
|
||||
}
|
||||
|
||||
public List<File> getJarClassPath(File file) throws IOException {
|
||||
String parent = file.getParent();
|
||||
JarFile jarFile = new JarFile(file);
|
||||
try {
|
||||
Manifest man = jarFile.getManifest();
|
||||
if (man == null)
|
||||
return Collections.emptyList();
|
||||
|
||||
Attributes attr = man.getMainAttributes();
|
||||
if (attr == null)
|
||||
return Collections.emptyList();
|
||||
|
||||
String path = attr.getValue(Attributes.Name.CLASS_PATH);
|
||||
if (path == null)
|
||||
return Collections.emptyList();
|
||||
|
||||
List<File> list = new ArrayList<File>();
|
||||
|
||||
for (StringTokenizer st = new StringTokenizer(path); st.hasMoreTokens(); ) {
|
||||
String elt = st.nextToken();
|
||||
File f = (parent == null ? new File(elt) : new File(parent, elt));
|
||||
list.add(f);
|
||||
}
|
||||
|
||||
return list;
|
||||
} finally {
|
||||
jarFile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
881
jdkSrc/jdk8/com/sun/tools/javac/file/JavacFileManager.java
Normal file
881
jdkSrc/jdk8/com/sun/tools/javac/file/JavacFileManager.java
Normal file
@@ -0,0 +1,881 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.file;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
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;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeFile;
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
|
||||
import com.sun.tools.javac.util.BaseFileManager;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
|
||||
import static javax.tools.StandardLocation.*;
|
||||
|
||||
/**
|
||||
* This class provides access to the source, class and other files
|
||||
* used by the compiler and related tools.
|
||||
*
|
||||
* <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 JavacFileManager extends BaseFileManager implements StandardJavaFileManager {
|
||||
|
||||
public static char[] toArray(CharBuffer buffer) {
|
||||
if (buffer.hasArray())
|
||||
return ((CharBuffer)buffer.compact().flip()).array();
|
||||
else
|
||||
return buffer.toString().toCharArray();
|
||||
}
|
||||
|
||||
private FSInfo fsInfo;
|
||||
|
||||
private boolean contextUseOptimizedZip;
|
||||
private ZipFileIndexCache zipFileIndexCache;
|
||||
|
||||
private final Set<JavaFileObject.Kind> sourceOrClass =
|
||||
EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
|
||||
|
||||
protected boolean mmappedIO;
|
||||
protected boolean symbolFileEnabled;
|
||||
|
||||
protected enum SortFiles implements Comparator<File> {
|
||||
FORWARD {
|
||||
public int compare(File f1, File f2) {
|
||||
return f1.getName().compareTo(f2.getName());
|
||||
}
|
||||
},
|
||||
REVERSE {
|
||||
public int compare(File f1, File f2) {
|
||||
return -f1.getName().compareTo(f2.getName());
|
||||
}
|
||||
};
|
||||
};
|
||||
protected SortFiles sortFiles;
|
||||
|
||||
/**
|
||||
* Register a Context.Factory to create a JavacFileManager.
|
||||
*/
|
||||
public static void preRegister(Context context) {
|
||||
context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
|
||||
public JavaFileManager make(Context c) {
|
||||
return new JavacFileManager(c, true, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a JavacFileManager using a given context, optionally registering
|
||||
* it as the JavaFileManager for that context.
|
||||
*/
|
||||
public JavacFileManager(Context context, boolean register, Charset charset) {
|
||||
super(charset);
|
||||
if (register)
|
||||
context.put(JavaFileManager.class, this);
|
||||
setContext(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the context for JavacFileManager.
|
||||
*/
|
||||
@Override
|
||||
public void setContext(Context context) {
|
||||
super.setContext(context);
|
||||
|
||||
fsInfo = FSInfo.instance(context);
|
||||
|
||||
contextUseOptimizedZip = options.getBoolean("useOptimizedZip", true);
|
||||
if (contextUseOptimizedZip)
|
||||
zipFileIndexCache = ZipFileIndexCache.getSharedInstance();
|
||||
|
||||
mmappedIO = options.isSet("mmappedIO");
|
||||
symbolFileEnabled = !options.isSet("ignore.symbol.file");
|
||||
|
||||
String sf = options.get("sortFiles");
|
||||
if (sf != null) {
|
||||
sortFiles = (sf.equals("reverse") ? SortFiles.REVERSE : SortFiles.FORWARD);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not to use ct.sym as an alternate to rt.jar.
|
||||
*/
|
||||
public void setSymbolFileEnabled(boolean b) {
|
||||
symbolFileEnabled = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefaultBootClassPath() {
|
||||
return locations.isDefaultBootClassPath();
|
||||
}
|
||||
|
||||
public JavaFileObject getFileForInput(String name) {
|
||||
return getRegularFile(new File(name));
|
||||
}
|
||||
|
||||
public JavaFileObject getRegularFile(File file) {
|
||||
return new RegularFileObject(this, file);
|
||||
}
|
||||
|
||||
public JavaFileObject getFileForOutput(String classname,
|
||||
JavaFileObject.Kind kind,
|
||||
JavaFileObject sibling)
|
||||
throws IOException
|
||||
{
|
||||
return getJavaFileForOutput(CLASS_OUTPUT, classname, kind, sibling);
|
||||
}
|
||||
|
||||
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
|
||||
ListBuffer<File> files = new ListBuffer<File>();
|
||||
for (String name : names)
|
||||
files.append(new File(nullCheck(name)));
|
||||
return getJavaFileObjectsFromFiles(files.toList());
|
||||
}
|
||||
|
||||
public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
|
||||
return getJavaFileObjectsFromStrings(Arrays.asList(nullCheck(names)));
|
||||
}
|
||||
|
||||
private static boolean isValidName(String name) {
|
||||
// Arguably, isValidName should reject keywords (such as in SourceVersion.isName() ),
|
||||
// but the set of keywords depends on the source level, and we don't want
|
||||
// impls of JavaFileManager to have to be dependent on the source level.
|
||||
// Therefore we simply check that the argument is a sequence of identifiers
|
||||
// separated by ".".
|
||||
for (String s : name.split("\\.", -1)) {
|
||||
if (!SourceVersion.isIdentifier(s))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void validateClassName(String className) {
|
||||
if (!isValidName(className))
|
||||
throw new IllegalArgumentException("Invalid class name: " + className);
|
||||
}
|
||||
|
||||
private static void validatePackageName(String packageName) {
|
||||
if (packageName.length() > 0 && !isValidName(packageName))
|
||||
throw new IllegalArgumentException("Invalid packageName name: " + packageName);
|
||||
}
|
||||
|
||||
public static void testName(String name,
|
||||
boolean isValidPackageName,
|
||||
boolean isValidClassName)
|
||||
{
|
||||
try {
|
||||
validatePackageName(name);
|
||||
if (!isValidPackageName)
|
||||
throw new AssertionError("Invalid package name accepted: " + name);
|
||||
printAscii("Valid package name: \"%s\"", name);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (isValidPackageName)
|
||||
throw new AssertionError("Valid package name rejected: " + name);
|
||||
printAscii("Invalid package name: \"%s\"", name);
|
||||
}
|
||||
try {
|
||||
validateClassName(name);
|
||||
if (!isValidClassName)
|
||||
throw new AssertionError("Invalid class name accepted: " + name);
|
||||
printAscii("Valid class name: \"%s\"", name);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (isValidClassName)
|
||||
throw new AssertionError("Valid class name rejected: " + name);
|
||||
printAscii("Invalid class name: \"%s\"", name);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printAscii(String format, Object... args) {
|
||||
String message;
|
||||
try {
|
||||
final String ascii = "US-ASCII";
|
||||
message = new String(String.format(null, format, args).getBytes(ascii), ascii);
|
||||
} catch (java.io.UnsupportedEncodingException ex) {
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
System.out.println(message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert all files in subdirectory subdirectory of directory directory
|
||||
* which match fileKinds into resultList
|
||||
*/
|
||||
private void listDirectory(File directory,
|
||||
RelativeDirectory subdirectory,
|
||||
Set<JavaFileObject.Kind> fileKinds,
|
||||
boolean recurse,
|
||||
ListBuffer<JavaFileObject> resultList) {
|
||||
File d = subdirectory.getFile(directory);
|
||||
if (!caseMapCheck(d, subdirectory))
|
||||
return;
|
||||
|
||||
File[] files = d.listFiles();
|
||||
if (files == null)
|
||||
return;
|
||||
|
||||
if (sortFiles != null)
|
||||
Arrays.sort(files, sortFiles);
|
||||
|
||||
for (File f: files) {
|
||||
String fname = f.getName();
|
||||
if (f.isDirectory()) {
|
||||
if (recurse && SourceVersion.isIdentifier(fname)) {
|
||||
listDirectory(directory,
|
||||
new RelativeDirectory(subdirectory, fname),
|
||||
fileKinds,
|
||||
recurse,
|
||||
resultList);
|
||||
}
|
||||
} else {
|
||||
if (isValidFile(fname, fileKinds)) {
|
||||
JavaFileObject fe =
|
||||
new RegularFileObject(this, fname, new File(d, fname));
|
||||
resultList.append(fe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert all files in subdirectory subdirectory of archive archive
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* container is a directory, a zip file, or a non-existant path.
|
||||
* Insert all files in subdirectory subdirectory of container which
|
||||
* match fileKinds into resultList
|
||||
*/
|
||||
private void listContainer(File container,
|
||||
RelativeDirectory subdirectory,
|
||||
Set<JavaFileObject.Kind> fileKinds,
|
||||
boolean recurse,
|
||||
ListBuffer<JavaFileObject> resultList) {
|
||||
Archive archive = archives.get(container);
|
||||
if (archive == null) {
|
||||
// archives are not created for directories.
|
||||
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;
|
||||
}
|
||||
}
|
||||
listArchive(archive,
|
||||
subdirectory,
|
||||
fileKinds,
|
||||
recurse,
|
||||
resultList);
|
||||
}
|
||||
|
||||
private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
|
||||
JavaFileObject.Kind kind = getKind(s);
|
||||
return fileKinds.contains(kind);
|
||||
}
|
||||
|
||||
private static final boolean fileSystemIsCaseSensitive =
|
||||
File.separatorChar == '/';
|
||||
|
||||
/** Hack to make Windows case sensitive. Test whether given path
|
||||
* ends in a string of characters with the same case as given name.
|
||||
* Ignore file separators in both path and name.
|
||||
*/
|
||||
private boolean caseMapCheck(File f, RelativePath name) {
|
||||
if (fileSystemIsCaseSensitive) return true;
|
||||
// Note that getCanonicalPath() returns the case-sensitive
|
||||
// spelled file name.
|
||||
String path;
|
||||
try {
|
||||
path = f.getCanonicalPath();
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
char[] pcs = path.toCharArray();
|
||||
char[] ncs = name.path.toCharArray();
|
||||
int i = pcs.length - 1;
|
||||
int j = ncs.length - 1;
|
||||
while (i >= 0 && j >= 0) {
|
||||
while (i >= 0 && pcs[i] == File.separatorChar) i--;
|
||||
while (j >= 0 && ncs[j] == '/') j--;
|
||||
if (i >= 0 && j >= 0) {
|
||||
if (pcs[i] != ncs[j]) return false;
|
||||
i--;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
public class MissingArchive implements Archive {
|
||||
final File zipFileName;
|
||||
public MissingArchive(File name) {
|
||||
zipFileName = name;
|
||||
}
|
||||
public boolean contains(RelativePath name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
|
||||
public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getFiles(RelativeDirectory subdirectory) {
|
||||
return List.nil();
|
||||
}
|
||||
|
||||
public Set<RelativeDirectory> getSubdirectories() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MissingArchive[" + zipFileName + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/** A directory of zip files already opened.
|
||||
*/
|
||||
Map<File, Archive> archives = new HashMap<File,Archive>();
|
||||
|
||||
private static final String[] symbolFileLocation = { "lib", "ct.sym" };
|
||||
private static final RelativeDirectory symbolFilePrefix
|
||||
= new RelativeDirectory("META-INF/sym/rt.jar/");
|
||||
|
||||
/*
|
||||
* 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(File 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(File zipFileName, boolean useOptimizedZip) throws IOException {
|
||||
File origZipFileName = zipFileName;
|
||||
if (symbolFileEnabled && locations.isDefaultBootClassPathRtJar(zipFileName)) {
|
||||
File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
|
||||
if (new File(file.getName()).equals(new File("jre")))
|
||||
file = file.getParentFile();
|
||||
// file == ${jdk.home}
|
||||
for (String name : symbolFileLocation)
|
||||
file = new File(file, name);
|
||||
// file == ${jdk.home}/lib/ct.sym
|
||||
if (file.exists())
|
||||
zipFileName = file;
|
||||
}
|
||||
|
||||
Archive archive;
|
||||
try {
|
||||
|
||||
ZipFile zdir = null;
|
||||
|
||||
boolean usePreindexedCache = false;
|
||||
String preindexCacheLocation = null;
|
||||
|
||||
if (!useOptimizedZip) {
|
||||
zdir = new ZipFile(zipFileName);
|
||||
} 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 (origZipFileName == zipFileName) {
|
||||
if (!useOptimizedZip) {
|
||||
archive = new ZipArchive(this, zdir);
|
||||
} else {
|
||||
archive = new ZipFileIndexArchive(this,
|
||||
zipFileIndexCache.getZipFileIndex(zipFileName,
|
||||
null,
|
||||
usePreindexedCache,
|
||||
preindexCacheLocation,
|
||||
options.isSet("writezipindexfiles")));
|
||||
}
|
||||
} else {
|
||||
if (!useOptimizedZip) {
|
||||
archive = new SymbolArchive(this, origZipFileName, zdir, symbolFilePrefix);
|
||||
} else {
|
||||
archive = new ZipFileIndexArchive(this,
|
||||
zipFileIndexCache.getZipFileIndex(zipFileName,
|
||||
symbolFilePrefix,
|
||||
usePreindexedCache,
|
||||
preindexCacheLocation,
|
||||
options.isSet("writezipindexfiles")));
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
archive = new MissingArchive(zipFileName);
|
||||
} catch (ZipFileIndex.ZipFormatException zfe) {
|
||||
throw zfe;
|
||||
} catch (IOException ex) {
|
||||
if (zipFileName.exists())
|
||||
log.error("error.reading.file", zipFileName, getMessage(ex));
|
||||
archive = new MissingArchive(zipFileName);
|
||||
}
|
||||
|
||||
archives.put(origZipFileName, archive);
|
||||
return archive;
|
||||
}
|
||||
|
||||
/** Flush any output resources.
|
||||
*/
|
||||
public void flush() {
|
||||
contentCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the JavaFileManager, releasing resources.
|
||||
*/
|
||||
public void close() {
|
||||
for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) {
|
||||
Archive a = i.next();
|
||||
i.remove();
|
||||
try {
|
||||
a.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String defaultEncodingName;
|
||||
private String getDefaultEncodingName() {
|
||||
if (defaultEncodingName == null) {
|
||||
defaultEncodingName =
|
||||
new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
|
||||
}
|
||||
return defaultEncodingName;
|
||||
}
|
||||
|
||||
public ClassLoader getClassLoader(Location location) {
|
||||
nullCheck(location);
|
||||
Iterable<? extends File> path = getLocation(location);
|
||||
if (path == null)
|
||||
return null;
|
||||
ListBuffer<URL> lb = new ListBuffer<URL>();
|
||||
for (File f: path) {
|
||||
try {
|
||||
lb.append(f.toURI().toURL());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
return getClassLoader(lb.toArray(new URL[lb.size()]));
|
||||
}
|
||||
|
||||
public Iterable<JavaFileObject> list(Location location,
|
||||
String packageName,
|
||||
Set<JavaFileObject.Kind> kinds,
|
||||
boolean recurse)
|
||||
throws IOException
|
||||
{
|
||||
// validatePackageName(packageName);
|
||||
nullCheck(packageName);
|
||||
nullCheck(kinds);
|
||||
|
||||
Iterable<? extends File> path = getLocation(location);
|
||||
if (path == null)
|
||||
return List.nil();
|
||||
RelativeDirectory subdirectory = RelativeDirectory.forPackage(packageName);
|
||||
ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
|
||||
|
||||
for (File directory : path)
|
||||
listContainer(directory, subdirectory, kinds, recurse, results);
|
||||
return results.toList();
|
||||
}
|
||||
|
||||
public String inferBinaryName(Location location, JavaFileObject file) {
|
||||
file.getClass(); // null check
|
||||
location.getClass(); // null check
|
||||
// Need to match the path semantics of list(location, ...)
|
||||
Iterable<? extends File> path = getLocation(location);
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (file instanceof BaseFileObject) {
|
||||
return ((BaseFileObject) file).inferBinaryName(path);
|
||||
} else
|
||||
throw new IllegalArgumentException(file.getClass().getName());
|
||||
}
|
||||
|
||||
public boolean isSameFile(FileObject a, FileObject b) {
|
||||
nullCheck(a);
|
||||
nullCheck(b);
|
||||
if (!(a instanceof BaseFileObject))
|
||||
throw new IllegalArgumentException("Not supported: " + a);
|
||||
if (!(b instanceof BaseFileObject))
|
||||
throw new IllegalArgumentException("Not supported: " + b);
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
public boolean hasLocation(Location location) {
|
||||
return getLocation(location) != null;
|
||||
}
|
||||
|
||||
public JavaFileObject getJavaFileForInput(Location location,
|
||||
String className,
|
||||
JavaFileObject.Kind kind)
|
||||
throws IOException
|
||||
{
|
||||
nullCheck(location);
|
||||
// validateClassName(className);
|
||||
nullCheck(className);
|
||||
nullCheck(kind);
|
||||
if (!sourceOrClass.contains(kind))
|
||||
throw new IllegalArgumentException("Invalid kind: " + kind);
|
||||
return getFileForInput(location, RelativeFile.forClass(className, kind));
|
||||
}
|
||||
|
||||
public FileObject getFileForInput(Location location,
|
||||
String packageName,
|
||||
String relativeName)
|
||||
throws IOException
|
||||
{
|
||||
nullCheck(location);
|
||||
// validatePackageName(packageName);
|
||||
nullCheck(packageName);
|
||||
if (!isRelativeUri(relativeName))
|
||||
throw new IllegalArgumentException("Invalid relative name: " + relativeName);
|
||||
RelativeFile name = packageName.length() == 0
|
||||
? new RelativeFile(relativeName)
|
||||
: new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
|
||||
return getFileForInput(location, name);
|
||||
}
|
||||
|
||||
private JavaFileObject getFileForInput(Location location, RelativeFile name) throws IOException {
|
||||
Iterable<? extends File> path = getLocation(location);
|
||||
if (path == null)
|
||||
return null;
|
||||
|
||||
for (File dir: path) {
|
||||
Archive a = archives.get(dir);
|
||||
if (a == null) {
|
||||
if (fsInfo.isDirectory(dir)) {
|
||||
File f = name.getFile(dir);
|
||||
if (f.exists())
|
||||
return new RegularFileObject(this, f);
|
||||
continue;
|
||||
}
|
||||
// Not a directory, create the archive
|
||||
a = openArchive(dir);
|
||||
}
|
||||
// Process the archive
|
||||
if (a.contains(name)) {
|
||||
return a.getFileObject(name.dirname(), name.basename());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public JavaFileObject getJavaFileForOutput(Location location,
|
||||
String className,
|
||||
JavaFileObject.Kind kind,
|
||||
FileObject sibling)
|
||||
throws IOException
|
||||
{
|
||||
nullCheck(location);
|
||||
// validateClassName(className);
|
||||
nullCheck(className);
|
||||
nullCheck(kind);
|
||||
if (!sourceOrClass.contains(kind))
|
||||
throw new IllegalArgumentException("Invalid kind: " + kind);
|
||||
return getFileForOutput(location, RelativeFile.forClass(className, kind), sibling);
|
||||
}
|
||||
|
||||
public FileObject getFileForOutput(Location location,
|
||||
String packageName,
|
||||
String relativeName,
|
||||
FileObject sibling)
|
||||
throws IOException
|
||||
{
|
||||
nullCheck(location);
|
||||
// validatePackageName(packageName);
|
||||
nullCheck(packageName);
|
||||
if (!isRelativeUri(relativeName))
|
||||
throw new IllegalArgumentException("Invalid relative name: " + relativeName);
|
||||
RelativeFile name = packageName.length() == 0
|
||||
? new RelativeFile(relativeName)
|
||||
: new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
|
||||
return getFileForOutput(location, name, sibling);
|
||||
}
|
||||
|
||||
private JavaFileObject getFileForOutput(Location location,
|
||||
RelativeFile fileName,
|
||||
FileObject sibling)
|
||||
throws IOException
|
||||
{
|
||||
File dir;
|
||||
if (location == CLASS_OUTPUT) {
|
||||
if (getClassOutDir() != null) {
|
||||
dir = getClassOutDir();
|
||||
} else {
|
||||
File siblingDir = null;
|
||||
if (sibling != null && sibling instanceof RegularFileObject) {
|
||||
siblingDir = ((RegularFileObject)sibling).file.getParentFile();
|
||||
}
|
||||
return new RegularFileObject(this, new File(siblingDir, fileName.basename()));
|
||||
}
|
||||
} else if (location == SOURCE_OUTPUT) {
|
||||
dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
|
||||
} else {
|
||||
Iterable<? extends File> path = locations.getLocation(location);
|
||||
dir = null;
|
||||
for (File f: path) {
|
||||
dir = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
File file = fileName.getFile(dir); // null-safe
|
||||
return new RegularFileObject(this, file);
|
||||
|
||||
}
|
||||
|
||||
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
|
||||
Iterable<? extends File> files)
|
||||
{
|
||||
ArrayList<RegularFileObject> result;
|
||||
if (files instanceof Collection<?>)
|
||||
result = new ArrayList<RegularFileObject>(((Collection<?>)files).size());
|
||||
else
|
||||
result = new ArrayList<RegularFileObject>();
|
||||
for (File f: files)
|
||||
result.add(new RegularFileObject(this, nullCheck(f)));
|
||||
return result;
|
||||
}
|
||||
|
||||
public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
|
||||
return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files)));
|
||||
}
|
||||
|
||||
public void setLocation(Location location,
|
||||
Iterable<? extends File> path)
|
||||
throws IOException
|
||||
{
|
||||
nullCheck(location);
|
||||
locations.setLocation(location, path);
|
||||
}
|
||||
|
||||
public Iterable<? extends File> getLocation(Location location) {
|
||||
nullCheck(location);
|
||||
return locations.getLocation(location);
|
||||
}
|
||||
|
||||
private File getClassOutDir() {
|
||||
return locations.getOutputLocation(CLASS_OUTPUT);
|
||||
}
|
||||
|
||||
private File getSourceOutDir() {
|
||||
return locations.getOutputLocation(SOURCE_OUTPUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces the specification of a "relative" name as used in
|
||||
* {@linkplain #getFileForInput(Location,String,String)
|
||||
* getFileForInput}. This method must follow the rules defined in
|
||||
* that method, do not make any changes without consulting the
|
||||
* specification.
|
||||
*/
|
||||
protected static boolean isRelativeUri(URI uri) {
|
||||
if (uri.isAbsolute())
|
||||
return false;
|
||||
String path = uri.normalize().getPath();
|
||||
if (path.length() == 0 /* isEmpty() is mustang API */)
|
||||
return false;
|
||||
if (!path.equals(uri.getPath())) // implicitly checks for embedded . and ..
|
||||
return false;
|
||||
if (path.startsWith("/") || path.startsWith("./") || path.startsWith("../"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convenience method
|
||||
protected static boolean isRelativeUri(String u) {
|
||||
try {
|
||||
return isRelativeUri(new URI(u));
|
||||
} catch (URISyntaxException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a relative file name to a relative URI. This is
|
||||
* different from File.toURI as this method does not canonicalize
|
||||
* the file before creating the URI. Furthermore, no schema is
|
||||
* used.
|
||||
* @param file a relative file name
|
||||
* @return a relative URI
|
||||
* @throws IllegalArgumentException if the file name is not
|
||||
* relative according to the definition given in {@link
|
||||
* javax.tools.JavaFileManager#getFileForInput}
|
||||
*/
|
||||
public static String getRelativeName(File file) {
|
||||
if (!file.isAbsolute()) {
|
||||
String result = file.getPath().replace(File.separatorChar, '/');
|
||||
if (isRelativeUri(result))
|
||||
return result;
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid relative path: " + file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a detail message from an IOException.
|
||||
* Most, but not all, instances of IOException provide a non-null result
|
||||
* for getLocalizedMessage(). But some instances return null: in these
|
||||
* cases, fallover to getMessage(), and if even that is null, return the
|
||||
* name of the exception itself.
|
||||
* @param e an IOException
|
||||
* @return a string to include in a compiler diagnostic
|
||||
*/
|
||||
public static String getMessage(IOException e) {
|
||||
String s = e.getLocalizedMessage();
|
||||
if (s != null)
|
||||
return s;
|
||||
s = e.getMessage();
|
||||
if (s != null)
|
||||
return s;
|
||||
return e.toString();
|
||||
}
|
||||
}
|
||||
777
jdkSrc/jdk8/com/sun/tools/javac/file/Locations.java
Normal file
777
jdkSrc/jdk8/com/sun/tools/javac/file/Locations.java
Normal file
@@ -0,0 +1,777 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.javac.file;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Iterator;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.zip.ZipFile;
|
||||
import javax.tools.JavaFileManager.Location;
|
||||
import javax.tools.StandardLocation;
|
||||
|
||||
import com.sun.tools.javac.code.Lint;
|
||||
import com.sun.tools.javac.main.Option;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
import com.sun.tools.javac.util.Log;
|
||||
import com.sun.tools.javac.util.Options;
|
||||
import com.sun.tools.javac.util.StringUtils;
|
||||
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import static javax.tools.StandardLocation.*;
|
||||
import static com.sun.tools.javac.main.Option.*;
|
||||
|
||||
/** This class converts command line arguments, environment variables
|
||||
* and system properties (in File.pathSeparator-separated String form)
|
||||
* into a boot class path, user class path, and source path (in
|
||||
* {@code Collection<String>} form).
|
||||
*
|
||||
* <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 Locations {
|
||||
|
||||
/** The log to use for warning output */
|
||||
private Log log;
|
||||
|
||||
/** Collection of command-line options */
|
||||
private Options options;
|
||||
|
||||
/** Handler for -Xlint options */
|
||||
private Lint lint;
|
||||
|
||||
/** Access to (possibly cached) file info */
|
||||
private FSInfo fsInfo;
|
||||
|
||||
/** Whether to warn about non-existent path elements */
|
||||
private boolean warn;
|
||||
|
||||
// TODO: remove need for this
|
||||
private boolean inited = false; // TODO? caching bad?
|
||||
|
||||
public Locations() {
|
||||
initHandlers();
|
||||
}
|
||||
|
||||
public void update(Log log, Options options, Lint lint, FSInfo fsInfo) {
|
||||
this.log = log;
|
||||
this.options = options;
|
||||
this.lint = lint;
|
||||
this.fsInfo = fsInfo;
|
||||
}
|
||||
|
||||
public Collection<File> bootClassPath() {
|
||||
return getLocation(PLATFORM_CLASS_PATH);
|
||||
}
|
||||
|
||||
public boolean isDefaultBootClassPath() {
|
||||
BootClassPathLocationHandler h =
|
||||
(BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
|
||||
return h.isDefault();
|
||||
}
|
||||
|
||||
boolean isDefaultBootClassPathRtJar(File file) {
|
||||
BootClassPathLocationHandler h =
|
||||
(BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
|
||||
return h.isDefaultRtJar(file);
|
||||
}
|
||||
|
||||
public Collection<File> userClassPath() {
|
||||
return getLocation(CLASS_PATH);
|
||||
}
|
||||
|
||||
public Collection<File> sourcePath() {
|
||||
Collection<File> p = getLocation(SOURCE_PATH);
|
||||
// TODO: this should be handled by the LocationHandler
|
||||
return p == null || p.isEmpty() ? null : p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a path into its elements. Empty path elements will be ignored.
|
||||
* @param path The path to be split
|
||||
* @return The elements of the path
|
||||
*/
|
||||
private static Iterable<File> getPathEntries(String path) {
|
||||
return getPathEntries(path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a path into its elements. If emptyPathDefault is not null, all
|
||||
* empty elements in the path, including empty elements at either end of
|
||||
* the path, will be replaced with the value of emptyPathDefault.
|
||||
* @param path The path to be split
|
||||
* @param emptyPathDefault The value to substitute for empty path elements,
|
||||
* or null, to ignore empty path elements
|
||||
* @return The elements of the path
|
||||
*/
|
||||
private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
|
||||
ListBuffer<File> entries = new ListBuffer<File>();
|
||||
int start = 0;
|
||||
while (start <= path.length()) {
|
||||
int sep = path.indexOf(File.pathSeparatorChar, start);
|
||||
if (sep == -1)
|
||||
sep = path.length();
|
||||
if (start < sep)
|
||||
entries.add(new File(path.substring(start, sep)));
|
||||
else if (emptyPathDefault != null)
|
||||
entries.add(emptyPathDefault);
|
||||
start = sep + 1;
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class to help evaluate a path option.
|
||||
* Duplicate entries are ignored, jar class paths can be expanded.
|
||||
*/
|
||||
private class Path extends LinkedHashSet<File> {
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
private boolean expandJarClassPaths = false;
|
||||
private Set<File> canonicalValues = new HashSet<File>();
|
||||
|
||||
public Path expandJarClassPaths(boolean x) {
|
||||
expandJarClassPaths = x;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** What to use when path element is the empty string */
|
||||
private File emptyPathDefault = null;
|
||||
|
||||
public Path emptyPathDefault(File x) {
|
||||
emptyPathDefault = x;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Path() { super(); }
|
||||
|
||||
public Path addDirectories(String dirs, boolean warn) {
|
||||
boolean prev = expandJarClassPaths;
|
||||
expandJarClassPaths = true;
|
||||
try {
|
||||
if (dirs != null)
|
||||
for (File dir : getPathEntries(dirs))
|
||||
addDirectory(dir, warn);
|
||||
return this;
|
||||
} finally {
|
||||
expandJarClassPaths = prev;
|
||||
}
|
||||
}
|
||||
|
||||
public Path addDirectories(String dirs) {
|
||||
return addDirectories(dirs, warn);
|
||||
}
|
||||
|
||||
private void addDirectory(File dir, boolean warn) {
|
||||
if (!dir.isDirectory()) {
|
||||
if (warn)
|
||||
log.warning(Lint.LintCategory.PATH,
|
||||
"dir.path.element.not.found", dir);
|
||||
return;
|
||||
}
|
||||
|
||||
File[] files = dir.listFiles();
|
||||
if (files == null)
|
||||
return;
|
||||
|
||||
for (File direntry : files) {
|
||||
if (isArchive(direntry))
|
||||
addFile(direntry, warn);
|
||||
}
|
||||
}
|
||||
|
||||
public Path addFiles(String files, boolean warn) {
|
||||
if (files != null) {
|
||||
addFiles(getPathEntries(files, emptyPathDefault), warn);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Path addFiles(String files) {
|
||||
return addFiles(files, warn);
|
||||
}
|
||||
|
||||
public Path addFiles(Iterable<? extends File> files, boolean warn) {
|
||||
if (files != null) {
|
||||
for (File file: files)
|
||||
addFile(file, warn);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Path addFiles(Iterable<? extends File> files) {
|
||||
return addFiles(files, warn);
|
||||
}
|
||||
|
||||
public void addFile(File file, boolean warn) {
|
||||
if (contains(file)) {
|
||||
// discard duplicates
|
||||
return;
|
||||
}
|
||||
|
||||
if (! fsInfo.exists(file)) {
|
||||
/* No such file or directory exists */
|
||||
if (warn) {
|
||||
log.warning(Lint.LintCategory.PATH,
|
||||
"path.element.not.found", file);
|
||||
}
|
||||
super.add(file);
|
||||
return;
|
||||
}
|
||||
|
||||
File canonFile = fsInfo.getCanonicalFile(file);
|
||||
if (canonicalValues.contains(canonFile)) {
|
||||
/* Discard duplicates and avoid infinite recursion */
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsInfo.isFile(file)) {
|
||||
/* File is an ordinary file. */
|
||||
if (!isArchive(file)) {
|
||||
/* Not a recognized extension; open it to see if
|
||||
it looks like a valid zip file. */
|
||||
try {
|
||||
ZipFile z = new ZipFile(file);
|
||||
z.close();
|
||||
if (warn) {
|
||||
log.warning(Lint.LintCategory.PATH,
|
||||
"unexpected.archive.file", file);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// FIXME: include e.getLocalizedMessage in warning
|
||||
if (warn) {
|
||||
log.warning(Lint.LintCategory.PATH,
|
||||
"invalid.archive.file", file);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now what we have left is either a directory or a file name
|
||||
conforming to archive naming convention */
|
||||
super.add(file);
|
||||
canonicalValues.add(canonFile);
|
||||
|
||||
if (expandJarClassPaths && fsInfo.isFile(file))
|
||||
addJarClassPath(file, warn);
|
||||
}
|
||||
|
||||
// Adds referenced classpath elements from a jar's Class-Path
|
||||
// Manifest entry. In some future release, we may want to
|
||||
// update this code to recognize URLs rather than simple
|
||||
// filenames, but if we do, we should redo all path-related code.
|
||||
private void addJarClassPath(File jarFile, boolean warn) {
|
||||
try {
|
||||
for (File f: fsInfo.getJarClassPath(jarFile)) {
|
||||
addFile(f, warn);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for handling support for the representation of Locations.
|
||||
* Implementations are responsible for handling the interactions between
|
||||
* the command line options for a location, and API access via setLocation.
|
||||
* @see #initHandlers
|
||||
* @see #getHandler
|
||||
*/
|
||||
protected abstract class LocationHandler {
|
||||
final Location location;
|
||||
final Set<Option> options;
|
||||
|
||||
/**
|
||||
* Create a handler. The location and options provide a way to map
|
||||
* from a location or an option to the corresponding handler.
|
||||
* @see #initHandlers
|
||||
*/
|
||||
protected LocationHandler(Location location, Option... options) {
|
||||
this.location = location;
|
||||
this.options = options.length == 0 ?
|
||||
EnumSet.noneOf(Option.class):
|
||||
EnumSet.copyOf(Arrays.asList(options));
|
||||
}
|
||||
|
||||
// TODO: TEMPORARY, while Options still used for command line options
|
||||
void update(Options optionTable) {
|
||||
for (Option o: options) {
|
||||
String v = optionTable.get(o);
|
||||
if (v != null) {
|
||||
handleOption(o, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @see JavaFileManager#handleOption */
|
||||
abstract boolean handleOption(Option option, String value);
|
||||
/** @see StandardJavaFileManager#getLocation */
|
||||
abstract Collection<File> getLocation();
|
||||
/** @see StandardJavaFileManager#setLocation */
|
||||
abstract void setLocation(Iterable<? extends File> files) throws IOException;
|
||||
}
|
||||
|
||||
/**
|
||||
* General purpose implementation for output locations,
|
||||
* such as -d/CLASS_OUTPUT and -s/SOURCE_OUTPUT.
|
||||
* All options are treated as equivalent (i.e. aliases.)
|
||||
* The value is a single file, possibly null.
|
||||
*/
|
||||
private class OutputLocationHandler extends LocationHandler {
|
||||
private File outputDir;
|
||||
|
||||
OutputLocationHandler(Location location, Option... options) {
|
||||
super(location, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean handleOption(Option option, String value) {
|
||||
if (!options.contains(option))
|
||||
return false;
|
||||
|
||||
// TODO: could/should validate outputDir exists and is a directory
|
||||
// need to decide how best to report issue for benefit of
|
||||
// direct API call on JavaFileManager.handleOption(specifies IAE)
|
||||
// vs. command line decoding.
|
||||
outputDir = new File(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
Collection<File> getLocation() {
|
||||
return (outputDir == null) ? null : Collections.singleton(outputDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setLocation(Iterable<? extends File> files) throws IOException {
|
||||
if (files == null) {
|
||||
outputDir = null;
|
||||
} else {
|
||||
Iterator<? extends File> pathIter = files.iterator();
|
||||
if (!pathIter.hasNext())
|
||||
throw new IllegalArgumentException("empty path for directory");
|
||||
File dir = pathIter.next();
|
||||
if (pathIter.hasNext())
|
||||
throw new IllegalArgumentException("path too long for directory");
|
||||
if (!dir.exists())
|
||||
throw new FileNotFoundException(dir + ": does not exist");
|
||||
else if (!dir.isDirectory())
|
||||
throw new IOException(dir + ": not a directory");
|
||||
outputDir = dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* General purpose implementation for search path locations,
|
||||
* such as -sourcepath/SOURCE_PATH and -processorPath/ANNOTATION_PROCESS_PATH.
|
||||
* All options are treated as equivalent (i.e. aliases.)
|
||||
* The value is an ordered set of files and/or directories.
|
||||
*/
|
||||
private class SimpleLocationHandler extends LocationHandler {
|
||||
protected Collection<File> searchPath;
|
||||
|
||||
SimpleLocationHandler(Location location, Option... options) {
|
||||
super(location, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean handleOption(Option option, String value) {
|
||||
if (!options.contains(option))
|
||||
return false;
|
||||
searchPath = value == null ? null :
|
||||
Collections.unmodifiableCollection(createPath().addFiles(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
Collection<File> getLocation() {
|
||||
return searchPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setLocation(Iterable<? extends File> files) {
|
||||
Path p;
|
||||
if (files == null) {
|
||||
p = computePath(null);
|
||||
} else {
|
||||
p = createPath().addFiles(files);
|
||||
}
|
||||
searchPath = Collections.unmodifiableCollection(p);
|
||||
}
|
||||
|
||||
protected Path computePath(String value) {
|
||||
return createPath().addFiles(value);
|
||||
}
|
||||
|
||||
protected Path createPath() {
|
||||
return new Path();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtype of SimpleLocationHandler for -classpath/CLASS_PATH.
|
||||
* If no value is given, a default is provided, based on system properties
|
||||
* and other values.
|
||||
*/
|
||||
private class ClassPathLocationHandler extends SimpleLocationHandler {
|
||||
ClassPathLocationHandler() {
|
||||
super(StandardLocation.CLASS_PATH,
|
||||
Option.CLASSPATH, Option.CP);
|
||||
}
|
||||
|
||||
@Override
|
||||
Collection<File> getLocation() {
|
||||
lazy();
|
||||
return searchPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Path computePath(String value) {
|
||||
String cp = value;
|
||||
|
||||
// CLASSPATH environment variable when run from `javac'.
|
||||
if (cp == null) cp = System.getProperty("env.class.path");
|
||||
|
||||
// If invoked via a java VM (not the javac launcher), use the
|
||||
// platform class path
|
||||
if (cp == null && System.getProperty("application.home") == null)
|
||||
cp = System.getProperty("java.class.path");
|
||||
|
||||
// Default to current working directory.
|
||||
if (cp == null) cp = ".";
|
||||
|
||||
return createPath().addFiles(cp);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Path createPath() {
|
||||
return new Path()
|
||||
.expandJarClassPaths(true) // Only search user jars for Class-Paths
|
||||
.emptyPathDefault(new File(".")); // Empty path elt ==> current directory
|
||||
}
|
||||
|
||||
private void lazy() {
|
||||
if (searchPath == null)
|
||||
setLocation(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom subtype of LocationHandler for PLATFORM_CLASS_PATH.
|
||||
* Various options are supported for different components of the
|
||||
* platform class path.
|
||||
* Setting a value with setLocation overrides all existing option values.
|
||||
* Setting any option overrides any value set with setLocation, and reverts
|
||||
* to using default values for options that have not been set.
|
||||
* Setting -bootclasspath or -Xbootclasspath overrides any existing
|
||||
* value for -Xbootclasspath/p: and -Xbootclasspath/a:.
|
||||
*/
|
||||
private class BootClassPathLocationHandler extends LocationHandler {
|
||||
private Collection<File> searchPath;
|
||||
final Map<Option, String> optionValues = new EnumMap<Option,String>(Option.class);
|
||||
|
||||
/**
|
||||
* rt.jar as found on the default bootclasspath.
|
||||
* If the user specified a bootclasspath, null is used.
|
||||
*/
|
||||
private File defaultBootClassPathRtJar = null;
|
||||
|
||||
/**
|
||||
* Is bootclasspath the default?
|
||||
*/
|
||||
private boolean isDefaultBootClassPath;
|
||||
|
||||
BootClassPathLocationHandler() {
|
||||
super(StandardLocation.PLATFORM_CLASS_PATH,
|
||||
Option.BOOTCLASSPATH, Option.XBOOTCLASSPATH,
|
||||
Option.XBOOTCLASSPATH_PREPEND,
|
||||
Option.XBOOTCLASSPATH_APPEND,
|
||||
Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
|
||||
Option.EXTDIRS, Option.DJAVA_EXT_DIRS);
|
||||
}
|
||||
|
||||
boolean isDefault() {
|
||||
lazy();
|
||||
return isDefaultBootClassPath;
|
||||
}
|
||||
|
||||
boolean isDefaultRtJar(File file) {
|
||||
lazy();
|
||||
return file.equals(defaultBootClassPathRtJar);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean handleOption(Option option, String value) {
|
||||
if (!options.contains(option))
|
||||
return false;
|
||||
|
||||
option = canonicalize(option);
|
||||
optionValues.put(option, value);
|
||||
if (option == BOOTCLASSPATH) {
|
||||
optionValues.remove(XBOOTCLASSPATH_PREPEND);
|
||||
optionValues.remove(XBOOTCLASSPATH_APPEND);
|
||||
}
|
||||
searchPath = null; // reset to "uninitialized"
|
||||
return true;
|
||||
}
|
||||
// where
|
||||
// TODO: would be better if option aliasing was handled at a higher
|
||||
// level
|
||||
private Option canonicalize(Option option) {
|
||||
switch (option) {
|
||||
case XBOOTCLASSPATH:
|
||||
return Option.BOOTCLASSPATH;
|
||||
case DJAVA_ENDORSED_DIRS:
|
||||
return Option.ENDORSEDDIRS;
|
||||
case DJAVA_EXT_DIRS:
|
||||
return Option.EXTDIRS;
|
||||
default:
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
Collection<File> getLocation() {
|
||||
lazy();
|
||||
return searchPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setLocation(Iterable<? extends File> files) {
|
||||
if (files == null) {
|
||||
searchPath = null; // reset to "uninitialized"
|
||||
} else {
|
||||
defaultBootClassPathRtJar = null;
|
||||
isDefaultBootClassPath = false;
|
||||
Path p = new Path().addFiles(files, false);
|
||||
searchPath = Collections.unmodifiableCollection(p);
|
||||
optionValues.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Path computePath() {
|
||||
defaultBootClassPathRtJar = null;
|
||||
Path path = new Path();
|
||||
|
||||
String bootclasspathOpt = optionValues.get(BOOTCLASSPATH);
|
||||
String endorseddirsOpt = optionValues.get(ENDORSEDDIRS);
|
||||
String extdirsOpt = optionValues.get(EXTDIRS);
|
||||
String xbootclasspathPrependOpt = optionValues.get(XBOOTCLASSPATH_PREPEND);
|
||||
String xbootclasspathAppendOpt = optionValues.get(XBOOTCLASSPATH_APPEND);
|
||||
path.addFiles(xbootclasspathPrependOpt);
|
||||
|
||||
if (endorseddirsOpt != null)
|
||||
path.addDirectories(endorseddirsOpt);
|
||||
else
|
||||
path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
|
||||
|
||||
if (bootclasspathOpt != null) {
|
||||
path.addFiles(bootclasspathOpt);
|
||||
} else {
|
||||
// Standard system classes for this compiler's release.
|
||||
String files = System.getProperty("sun.boot.class.path");
|
||||
path.addFiles(files, false);
|
||||
File rt_jar = new File("rt.jar");
|
||||
for (File file : getPathEntries(files)) {
|
||||
if (new File(file.getName()).equals(rt_jar))
|
||||
defaultBootClassPathRtJar = file;
|
||||
}
|
||||
}
|
||||
|
||||
path.addFiles(xbootclasspathAppendOpt);
|
||||
|
||||
// Strictly speaking, standard extensions are not bootstrap
|
||||
// classes, but we treat them identically, so we'll pretend
|
||||
// that they are.
|
||||
if (extdirsOpt != null)
|
||||
path.addDirectories(extdirsOpt);
|
||||
else
|
||||
path.addDirectories(System.getProperty("java.ext.dirs"), false);
|
||||
|
||||
isDefaultBootClassPath =
|
||||
(xbootclasspathPrependOpt == null) &&
|
||||
(bootclasspathOpt == null) &&
|
||||
(xbootclasspathAppendOpt == null);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
private void lazy() {
|
||||
if (searchPath == null)
|
||||
searchPath = Collections.unmodifiableCollection(computePath());
|
||||
}
|
||||
}
|
||||
|
||||
Map<Location, LocationHandler> handlersForLocation;
|
||||
Map<Option, LocationHandler> handlersForOption;
|
||||
|
||||
void initHandlers() {
|
||||
handlersForLocation = new HashMap<Location, LocationHandler>();
|
||||
handlersForOption = new EnumMap<Option, LocationHandler>(Option.class);
|
||||
|
||||
LocationHandler[] handlers = {
|
||||
new BootClassPathLocationHandler(),
|
||||
new ClassPathLocationHandler(),
|
||||
new SimpleLocationHandler(StandardLocation.SOURCE_PATH, Option.SOURCEPATH),
|
||||
new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, Option.PROCESSORPATH),
|
||||
new OutputLocationHandler((StandardLocation.CLASS_OUTPUT), Option.D),
|
||||
new OutputLocationHandler((StandardLocation.SOURCE_OUTPUT), Option.S),
|
||||
new OutputLocationHandler((StandardLocation.NATIVE_HEADER_OUTPUT), Option.H)
|
||||
};
|
||||
|
||||
for (LocationHandler h: handlers) {
|
||||
handlersForLocation.put(h.location, h);
|
||||
for (Option o: h.options)
|
||||
handlersForOption.put(o, h);
|
||||
}
|
||||
}
|
||||
|
||||
boolean handleOption(Option option, String value) {
|
||||
LocationHandler h = handlersForOption.get(option);
|
||||
return (h == null ? false : h.handleOption(option, value));
|
||||
}
|
||||
|
||||
Collection<File> getLocation(Location location) {
|
||||
LocationHandler h = getHandler(location);
|
||||
return (h == null ? null : h.getLocation());
|
||||
}
|
||||
|
||||
File getOutputLocation(Location location) {
|
||||
if (!location.isOutputLocation())
|
||||
throw new IllegalArgumentException();
|
||||
LocationHandler h = getHandler(location);
|
||||
return ((OutputLocationHandler) h).outputDir;
|
||||
}
|
||||
|
||||
void setLocation(Location location, Iterable<? extends File> files) throws IOException {
|
||||
LocationHandler h = getHandler(location);
|
||||
if (h == null) {
|
||||
if (location.isOutputLocation())
|
||||
h = new OutputLocationHandler(location);
|
||||
else
|
||||
h = new SimpleLocationHandler(location);
|
||||
handlersForLocation.put(location, h);
|
||||
}
|
||||
h.setLocation(files);
|
||||
}
|
||||
|
||||
protected LocationHandler getHandler(Location location) {
|
||||
location.getClass(); // null check
|
||||
lazy();
|
||||
return handlersForLocation.get(location);
|
||||
}
|
||||
|
||||
// TOGO
|
||||
protected void lazy() {
|
||||
if (!inited) {
|
||||
warn = lint.isEnabled(Lint.LintCategory.PATH);
|
||||
|
||||
for (LocationHandler h: handlersForLocation.values()) {
|
||||
h.update(options);
|
||||
}
|
||||
|
||||
inited = true;
|
||||
}
|
||||
}
|
||||
|
||||
/** Is this the name of an archive file? */
|
||||
private boolean isArchive(File file) {
|
||||
String n = StringUtils.toLowerCase(file.getName());
|
||||
return fsInfo.isFile(file)
|
||||
&& (n.endsWith(".jar") || n.endsWith(".zip"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for converting a search path string to an array
|
||||
* of directory and JAR file URLs.
|
||||
*
|
||||
* Note that this method is called by apt and the DocletInvoker.
|
||||
*
|
||||
* @param path the search path string
|
||||
* @return the resulting array of directory and JAR file URLs
|
||||
*/
|
||||
public static URL[] pathToURLs(String path) {
|
||||
StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
|
||||
URL[] urls = new URL[st.countTokens()];
|
||||
int count = 0;
|
||||
while (st.hasMoreTokens()) {
|
||||
URL url = fileToURL(new File(st.nextToken()));
|
||||
if (url != null) {
|
||||
urls[count++] = url;
|
||||
}
|
||||
}
|
||||
urls = Arrays.copyOf(urls, count);
|
||||
return urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory or JAR file URL corresponding to the specified
|
||||
* local file name.
|
||||
*
|
||||
* @param file the File object
|
||||
* @return the resulting directory or JAR file URL, or null if unknown
|
||||
*/
|
||||
private static URL fileToURL(File file) {
|
||||
String name;
|
||||
try {
|
||||
name = file.getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
name = file.getAbsolutePath();
|
||||
}
|
||||
name = name.replace(File.separatorChar, '/');
|
||||
if (!name.startsWith("/")) {
|
||||
name = "/" + name;
|
||||
}
|
||||
// If the file does not exist, then assume that it's a directory
|
||||
if (!file.isFile()) {
|
||||
name = name + "/";
|
||||
}
|
||||
try {
|
||||
return new URL("file", "", name);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new IllegalArgumentException(file.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
251
jdkSrc/jdk8/com/sun/tools/javac/file/RegularFileObject.java
Normal file
251
jdkSrc/jdk8/com/sun/tools/javac/file/RegularFileObject.java
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.javac.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
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 javax.tools.JavaFileObject;
|
||||
import java.text.Normalizer;
|
||||
|
||||
/**
|
||||
* 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 File file;
|
||||
private Reference<File> absFileRef;
|
||||
final static boolean isMacOS = System.getProperty("os.name", "").contains("OS X");
|
||||
|
||||
public RegularFileObject(JavacFileManager fileManager, File f) {
|
||||
this(fileManager, f.getName(), f);
|
||||
}
|
||||
|
||||
public RegularFileObject(JavacFileManager fileManager, String name, File f) {
|
||||
super(fileManager);
|
||||
if (f.isDirectory()) {
|
||||
throw new IllegalArgumentException("directories not supported");
|
||||
}
|
||||
this.name = name;
|
||||
this.file = f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI toUri() {
|
||||
return file.toURI().normalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return file.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaFileObject.Kind getKind() {
|
||||
return getKind(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream openInputStream() throws IOException {
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
fileManager.flushCache(this);
|
||||
ensureParentDirectoriesExist();
|
||||
return new FileOutputStream(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||
CharBuffer cb = fileManager.getCachedContent(this);
|
||||
if (cb == null) {
|
||||
InputStream in = new FileInputStream(file);
|
||||
try {
|
||||
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);
|
||||
}
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer openWriter() throws IOException {
|
||||
fileManager.flushCache(this);
|
||||
ensureParentDirectoriesExist();
|
||||
return new OutputStreamWriter(new FileOutputStream(file), fileManager.getEncodingName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified() {
|
||||
return file.lastModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
return file.delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
|
||||
return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String inferBinaryName(Iterable<? extends File> path) {
|
||||
String fPath = file.getPath();
|
||||
//System.err.println("RegularFileObject " + file + " " +r.getPath());
|
||||
for (File dir: path) {
|
||||
//System.err.println("dir: " + dir);
|
||||
String dPath = dir.getPath();
|
||||
if (dPath.length() == 0)
|
||||
dPath = System.getProperty("user.dir");
|
||||
if (!dPath.endsWith(File.separator))
|
||||
dPath += File.separator;
|
||||
if (fPath.regionMatches(true, 0, dPath, 0, dPath.length())
|
||||
&& new File(fPath.substring(0, dPath.length())).equals(new File(dPath))) {
|
||||
String relativeName = fPath.substring(dPath.length());
|
||||
return removeExtension(relativeName).replace(File.separatorChar, '.');
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) {
|
||||
cn.getClass();
|
||||
// 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.getCanonicalFile().getName().equals(n);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ensureParentDirectoriesExist() throws IOException {
|
||||
if (!hasParents) {
|
||||
File parent = file.getParentFile();
|
||||
if (parent != null && !parent.exists()) {
|
||||
if (!parent.mkdirs()) {
|
||||
if (!parent.exists() || !parent.isDirectory()) {
|
||||
throw new IOException("could not create parent directories");
|
||||
}
|
||||
}
|
||||
}
|
||||
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 File getAbsoluteFile() {
|
||||
File absFile = (absFileRef == null ? null : absFileRef.get());
|
||||
if (absFile == null) {
|
||||
absFile = file.getAbsoluteFile();
|
||||
absFileRef = new SoftReference<File>(absFile);
|
||||
}
|
||||
return absFile;
|
||||
}
|
||||
}
|
||||
196
jdkSrc/jdk8/com/sun/tools/javac/file/RelativePath.java
Normal file
196
jdkSrc/jdk8/com/sun/tools/javac/file/RelativePath.java
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 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.File;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
/**
|
||||
* Used to represent a platform-neutral path within a platform-specific
|
||||
* container, such as a directory or zip file.
|
||||
* Internally, the file separator is always '/'.
|
||||
*
|
||||
* <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 RelativePath implements Comparable<RelativePath> {
|
||||
/**
|
||||
* @param p must use '/' as an internal separator
|
||||
*/
|
||||
protected RelativePath(String p) {
|
||||
path = p;
|
||||
}
|
||||
|
||||
public abstract RelativeDirectory dirname();
|
||||
|
||||
public abstract String basename();
|
||||
|
||||
public File getFile(File directory) {
|
||||
if (path.length() == 0)
|
||||
return directory;
|
||||
return new File(directory, path.replace('/', File.separatorChar));
|
||||
}
|
||||
|
||||
public int compareTo(RelativePath other) {
|
||||
return path.compareTo(other.path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof RelativePath))
|
||||
return false;
|
||||
return path.equals(((RelativePath) other).path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return path.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RelPath[" + path + "]";
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
protected final String path;
|
||||
|
||||
/**
|
||||
* Used to represent a platform-neutral subdirectory within a platform-specific
|
||||
* container, such as a directory or zip file.
|
||||
* Internally, the file separator is always '/', and if the path is not empty,
|
||||
* it always ends in a '/' as well.
|
||||
*/
|
||||
public static class RelativeDirectory extends RelativePath {
|
||||
|
||||
static RelativeDirectory forPackage(CharSequence packageName) {
|
||||
return new RelativeDirectory(packageName.toString().replace('.', '/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param p must use '/' as an internal separator
|
||||
*/
|
||||
public RelativeDirectory(String p) {
|
||||
super(p.length() == 0 || p.endsWith("/") ? p : p + "/");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param p must use '/' as an internal separator
|
||||
*/
|
||||
public RelativeDirectory(RelativeDirectory d, String p) {
|
||||
this(d.path + p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelativeDirectory dirname() {
|
||||
int l = path.length();
|
||||
if (l == 0)
|
||||
return this;
|
||||
int sep = path.lastIndexOf('/', l - 2);
|
||||
return new RelativeDirectory(path.substring(0, sep + 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String basename() {
|
||||
int l = path.length();
|
||||
if (l == 0)
|
||||
return path;
|
||||
int sep = path.lastIndexOf('/', l - 2);
|
||||
return path.substring(sep + 1, l - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this subdirectory "contains" the other path.
|
||||
* A subdirectory path does not contain itself.
|
||||
**/
|
||||
boolean contains(RelativePath other) {
|
||||
return other.path.length() > path.length() && other.path.startsWith(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RelativeDirectory[" + path + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to represent a platform-neutral file within a platform-specific
|
||||
* container, such as a directory or zip file.
|
||||
* Internally, the file separator is always '/'. It never ends in '/'.
|
||||
*/
|
||||
public static class RelativeFile extends RelativePath {
|
||||
static RelativeFile forClass(CharSequence className, JavaFileObject.Kind kind) {
|
||||
return new RelativeFile(className.toString().replace('.', '/') + kind.extension);
|
||||
}
|
||||
|
||||
public RelativeFile(String p) {
|
||||
super(p);
|
||||
if (p.endsWith("/"))
|
||||
throw new IllegalArgumentException(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param p must use '/' as an internal separator
|
||||
*/
|
||||
public RelativeFile(RelativeDirectory d, String p) {
|
||||
this(d.path + p);
|
||||
}
|
||||
|
||||
RelativeFile(RelativeDirectory d, RelativePath p) {
|
||||
this(d, p.path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelativeDirectory dirname() {
|
||||
int sep = path.lastIndexOf('/');
|
||||
return new RelativeDirectory(path.substring(0, sep + 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String basename() {
|
||||
int sep = path.lastIndexOf('/');
|
||||
return path.substring(sep + 1);
|
||||
}
|
||||
|
||||
ZipEntry getZipEntry(ZipFile zip) {
|
||||
return zip.getEntry(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RelativeFile[" + path + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
107
jdkSrc/jdk8/com/sun/tools/javac/file/SymbolArchive.java
Normal file
107
jdkSrc/jdk8/com/sun/tools/javac/file/SymbolArchive.java
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2009, 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.File;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
|
||||
import com.sun.tools.javac.file.RelativePath.RelativeFile;
|
||||
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 SymbolArchive extends ZipArchive {
|
||||
|
||||
final File origFile;
|
||||
final RelativeDirectory prefix;
|
||||
|
||||
public SymbolArchive(JavacFileManager fileManager, File orig, ZipFile zdir, RelativeDirectory prefix) throws IOException {
|
||||
super(fileManager, zdir, false);
|
||||
this.origFile = orig;
|
||||
this.prefix = prefix;
|
||||
initMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
void addZipEntry(ZipEntry entry) {
|
||||
String name = entry.getName();
|
||||
if (!name.startsWith(prefix.path)) {
|
||||
return;
|
||||
}
|
||||
name = name.substring(prefix.path.length());
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
|
||||
RelativeDirectory prefix_subdir = new RelativeDirectory(prefix, subdirectory.path);
|
||||
ZipEntry ze = new RelativeFile(prefix_subdir, file).getZipEntry(zfile);
|
||||
return new SymbolFileObject(this, file, ze);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SymbolArchive[" + zfile.getName() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* A subclass of JavaFileObject representing zip entries in a symbol file.
|
||||
*/
|
||||
public static class SymbolFileObject extends ZipFileObject {
|
||||
protected SymbolFileObject(SymbolArchive zarch, String name, ZipEntry entry) {
|
||||
super(zarch, name, entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String inferBinaryName(Iterable<? extends File> path) {
|
||||
String entryName = entry.getName();
|
||||
String prefix = ((SymbolArchive) zarch).prefix.path;
|
||||
if (entryName.startsWith(prefix))
|
||||
entryName = entryName.substring(prefix.length());
|
||||
return removeExtension(entryName).replace('/', '.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
288
jdkSrc/jdk8/com/sun/tools/javac/file/ZipArchive.java
Normal file
288
jdkSrc/jdk8/com/sun/tools/javac/file/ZipArchive.java
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2009, 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.File;
|
||||
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.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
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.List;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
/**
|
||||
* <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<RelativeDirectory,List<String>>();
|
||||
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 File getAbsoluteFile() {
|
||||
File absFile = (absFileRef == null ? null : absFileRef.get());
|
||||
if (absFile == null) {
|
||||
absFile = new File(zfile.getName()).getAbsoluteFile();
|
||||
absFileRef = new SoftReference<File>(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<File> 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;
|
||||
}
|
||||
|
||||
public URI toUri() {
|
||||
File zipFile = new File(zarch.zfile.getName());
|
||||
return createJarUri(zipFile, entry.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return zarch.zfile.getName() + "(" + entry.getName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return new File(zarch.zfile.getName()).getName() + "(" + entry + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaFileObject.Kind getKind() {
|
||||
return getKind(entry.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream openInputStream() throws IOException {
|
||||
return zarch.zfile.getInputStream(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||
CharBuffer cb = fileManager.getCachedContent(this);
|
||||
if (cb == null) {
|
||||
InputStream in = zarch.zfile.getInputStream(entry);
|
||||
try {
|
||||
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);
|
||||
}
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer openWriter() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified() {
|
||||
return entry.getTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
|
||||
return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String inferBinaryName(Iterable<? extends File> path) {
|
||||
String entryName = entry.getName();
|
||||
return removeExtension(entryName).replace('/', '.');
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
|
||||
cn.getClass();
|
||||
// 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())
|
||||
&& name.equals(o.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return zarch.getAbsoluteFile().hashCode() + name.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1169
jdkSrc/jdk8/com/sun/tools/javac/file/ZipFileIndex.java
Normal file
1169
jdkSrc/jdk8/com/sun/tools/javac/file/ZipFileIndex.java
Normal file
File diff suppressed because it is too large
Load Diff
254
jdkSrc/jdk8/com/sun/tools/javac/file/ZipFileIndexArchive.java
Normal file
254
jdkSrc/jdk8/com/sun/tools/javac/file/ZipFileIndexArchive.java
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2011, 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.util.Set;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
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 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.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 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 InputStream for this zip entry (file.)
|
||||
*/
|
||||
InputStream inputStream = null;
|
||||
|
||||
/** The name of the zip file where this entry resides.
|
||||
*/
|
||||
File zipName;
|
||||
|
||||
|
||||
ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, File zipFileName) {
|
||||
super(fileManager);
|
||||
this.name = entry.getFileName();
|
||||
this.zfIndex = zfIndex;
|
||||
this.entry = entry;
|
||||
this.zipName = zipFileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI toUri() {
|
||||
return createJarUri(zipName, getPrefixedEntryName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return zipName + "(" + getPrefixedEntryName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return zipName.getName() + "(" + entry.getName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaFileObject.Kind getKind() {
|
||||
return getKind(entry.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream openInputStream() throws IOException {
|
||||
if (inputStream == null) {
|
||||
Assert.checkNonNull(entry); // see constructor
|
||||
inputStream = new ByteArrayInputStream(zfIndex.read(entry));
|
||||
}
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||
CharBuffer cb = fileManager.getCachedContent(this);
|
||||
if (cb == null) {
|
||||
InputStream in = new ByteArrayInputStream(zfIndex.read(entry));
|
||||
try {
|
||||
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);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer openWriter() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified() {
|
||||
return entry.getLastModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
|
||||
return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String inferBinaryName(Iterable<? extends File> 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
|
||||
public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
|
||||
cn.getClass(); // null check
|
||||
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())
|
||||
&& name.equals(o.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return zfIndex.getAbsoluteFile().hashCode() + name.hashCode();
|
||||
}
|
||||
|
||||
private String getPrefixedEntryName() {
|
||||
if (zfIndex.symbolFilePrefix != null)
|
||||
return zfIndex.symbolFilePrefix.path + entry.getName();
|
||||
else
|
||||
return entry.getName();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
149
jdkSrc/jdk8/com/sun/tools/javac/file/ZipFileIndexCache.java
Normal file
149
jdkSrc/jdk8/com/sun/tools/javac/file/ZipFileIndexCache.java
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, 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 com.sun.tools.javac.file.RelativePath.RelativeDirectory;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/** A cache for ZipFileIndex objects. */
|
||||
public class ZipFileIndexCache {
|
||||
|
||||
private final Map<File, ZipFileIndex> map =
|
||||
new HashMap<File, ZipFileIndex>();
|
||||
|
||||
/** 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<ZipFileIndex>();
|
||||
|
||||
zipFileIndexes.addAll(map.values());
|
||||
|
||||
if (openedOnly) {
|
||||
for(ZipFileIndex elem : zipFileIndexes) {
|
||||
if (!elem.isOpen()) {
|
||||
zipFileIndexes.remove(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return zipFileIndexes;
|
||||
}
|
||||
|
||||
public synchronized ZipFileIndex getZipFileIndex(File zipFile,
|
||||
RelativeDirectory symbolFilePrefix,
|
||||
boolean useCache, String cacheLocation,
|
||||
boolean writeIndex) throws IOException {
|
||||
ZipFileIndex zi = getExistingZipIndex(zipFile);
|
||||
|
||||
if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
|
||||
zi = new ZipFileIndex(zipFile, symbolFilePrefix, writeIndex,
|
||||
useCache, cacheLocation);
|
||||
map.put(zipFile, zi);
|
||||
}
|
||||
return zi;
|
||||
}
|
||||
|
||||
public synchronized ZipFileIndex getExistingZipIndex(File zipFile) {
|
||||
return map.get(zipFile);
|
||||
}
|
||||
|
||||
public synchronized void clearCache() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public synchronized void clearCache(long timeNotUsed) {
|
||||
Iterator<File> cachedFileIterator = map.keySet().iterator();
|
||||
while (cachedFileIterator.hasNext()) {
|
||||
File cachedFile = cachedFileIterator.next();
|
||||
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(File 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user