--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java Tue Dec 13 10:48:18 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java Tue Dec 13 10:49:28 2016 +0100
@@ -51,6 +51,9 @@
import static javax.tools.StandardLocation.CLASS_OUTPUT;
import com.sun.tools.javac.code.Lint;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
@@ -114,10 +117,12 @@
*/
private class FilerOutputFileObject extends ForwardingFileObject<FileObject> {
private boolean opened = false;
+ private ModuleSymbol mod;
private String name;
- FilerOutputFileObject(String name, FileObject fileObject) {
+ FilerOutputFileObject(ModuleSymbol mod, String name, FileObject fileObject) {
super(fileObject);
+ this.mod = mod;
this.name = name;
}
@@ -126,7 +131,7 @@
if (opened)
throw new IOException(ALREADY_OPENED);
opened = true;
- return new FilerOutputStream(name, fileObject);
+ return new FilerOutputStream(mod, name, fileObject);
}
@Override @DefinedBy(Api.COMPILER)
@@ -134,7 +139,7 @@
if (opened)
throw new IOException(ALREADY_OPENED);
opened = true;
- return new FilerWriter(name, fileObject);
+ return new FilerWriter(mod, name, fileObject);
}
// Three anti-literacy methods
@@ -161,8 +166,8 @@
private class FilerOutputJavaFileObject extends FilerOutputFileObject implements JavaFileObject {
private final JavaFileObject javaFileObject;
- FilerOutputJavaFileObject(String name, JavaFileObject javaFileObject) {
- super(name, javaFileObject);
+ FilerOutputJavaFileObject(ModuleSymbol mod, String name, JavaFileObject javaFileObject) {
+ super(mod, name, javaFileObject);
this.javaFileObject = javaFileObject;
}
@@ -248,6 +253,7 @@
* when they are closed.
*/
private class FilerOutputStream extends FilterOutputStream {
+ ModuleSymbol mod;
String typeName;
FileObject fileObject;
boolean closed = false;
@@ -256,8 +262,9 @@
* @param typeName name of class or {@code null} if just a
* binary file
*/
- FilerOutputStream(String typeName, FileObject fileObject) throws IOException {
+ FilerOutputStream(ModuleSymbol mod, String typeName, FileObject fileObject) throws IOException {
super(fileObject.openOutputStream());
+ this.mod = mod;
this.typeName = typeName;
this.fileObject = fileObject;
}
@@ -270,7 +277,7 @@
* stream, still try to process the file.
*/
- closeFileObject(typeName, fileObject);
+ closeFileObject(mod, typeName, fileObject);
out.close();
}
}
@@ -282,6 +289,7 @@
* closed.
*/
private class FilerWriter extends FilterWriter {
+ ModuleSymbol mod;
String typeName;
FileObject fileObject;
boolean closed = false;
@@ -291,8 +299,9 @@
* @param typeName name of source file or {@code null} if just a
* text file
*/
- FilerWriter(String typeName, FileObject fileObject) throws IOException {
+ FilerWriter(ModuleSymbol mod, String typeName, FileObject fileObject) throws IOException {
super(fileObject.openWriter());
+ this.mod = mod;
this.typeName = typeName;
this.fileObject = fileObject;
}
@@ -305,7 +314,7 @@
* Writer, still try to process the file.
*/
- closeFileObject(typeName, fileObject);
+ closeFileObject(mod, typeName, fileObject);
out.close();
}
}
@@ -313,6 +322,9 @@
JavaFileManager fileManager;
Log log;
+ Modules modules;
+ Names names;
+ Symtab syms;
Context context;
boolean lastRound;
@@ -340,7 +352,7 @@
* This set must be synchronized. Its iterators should preserve
* insertion order.
*/
- private final Map<String, JavaFileObject> generatedClasses;
+ private final Map<ModuleSymbol, Map<String, JavaFileObject>> generatedClasses;
/**
* JavaFileObjects for source files closed in this round. This
@@ -353,13 +365,13 @@
* Names of all created source files. Its iterators should
* preserve insertion order.
*/
- private final Set<String> aggregateGeneratedSourceNames;
+ private final Set<Pair<ModuleSymbol, String>> aggregateGeneratedSourceNames;
/**
* Names of all created class files. Its iterators should
* preserve insertion order.
*/
- private final Set<String> aggregateGeneratedClassNames;
+ private final Set<Pair<ModuleSymbol, String>> aggregateGeneratedClassNames;
JavacFiler(Context context) {
@@ -367,12 +379,15 @@
fileManager = context.get(JavaFileManager.class);
log = Log.instance(context);
+ modules = Modules.instance(context);
+ names = Names.instance(context);
+ syms = Symtab.instance(context);
fileObjectHistory = synchronizedSet(new LinkedHashSet<FileObject>());
generatedSourceNames = synchronizedSet(new LinkedHashSet<String>());
generatedSourceFileObjects = synchronizedSet(new LinkedHashSet<JavaFileObject>());
- generatedClasses = synchronizedMap(new LinkedHashMap<String, JavaFileObject>());
+ generatedClasses = synchronizedMap(new LinkedHashMap<>());
openTypeNames = synchronizedSet(new LinkedHashSet<String>());
@@ -382,19 +397,51 @@
lint = (Lint.instance(context)).isEnabled(PROCESSING);
}
- @DefinedBy(Api.ANNOTATION_PROCESSING)
- public JavaFileObject createSourceFile(CharSequence name,
+ @Override @DefinedBy(Api.ANNOTATION_PROCESSING)
+ public JavaFileObject createSourceFile(CharSequence nameAndModule,
Element... originatingElements) throws IOException {
- return createSourceOrClassFile(true, name.toString());
+ Pair<ModuleSymbol, String> moduleAndClass = checkOrInferModule(nameAndModule);
+ return createSourceOrClassFile(moduleAndClass.fst, true, moduleAndClass.snd);
+ }
+
+ @Override @DefinedBy(Api.ANNOTATION_PROCESSING)
+ public JavaFileObject createClassFile(CharSequence nameAndModule,
+ Element... originatingElements) throws IOException {
+ Pair<ModuleSymbol, String> moduleAndClass = checkOrInferModule(nameAndModule);
+ return createSourceOrClassFile(moduleAndClass.fst, false, moduleAndClass.snd);
}
- @DefinedBy(Api.ANNOTATION_PROCESSING)
- public JavaFileObject createClassFile(CharSequence name,
- Element... originatingElements) throws IOException {
- return createSourceOrClassFile(false, name.toString());
+ private Pair<ModuleSymbol, String> checkOrInferModule(CharSequence moduleAndPkg) throws FilerException {
+ String moduleAndPkgString = moduleAndPkg.toString();
+ int slash = moduleAndPkgString.indexOf('/');
+
+ if (slash != (-1)) {
+ //module name specified:
+ String module = moduleAndPkgString.substring(0, slash);
+
+ ModuleSymbol explicitModule = syms.getModule(names.fromString(module));
+
+ if (explicitModule == null) {
+ throw new FilerException("Module: " + module + " does not exist.");
+ }
+
+ if (!modules.isRootModule(explicitModule)) {
+ throw new FilerException("Cannot write to the given module!");
+ }
+
+ return Pair.of(explicitModule, moduleAndPkgString.substring(slash + 1));
+ } else {
+ if (modules.multiModuleMode) {
+ throw new FilerException("No module to write to specified!");
+ }
+
+ return Pair.of(modules.getDefaultModule(), moduleAndPkgString);
+ }
}
- private JavaFileObject createSourceOrClassFile(boolean isSourceFile, String name) throws IOException {
+ private JavaFileObject createSourceOrClassFile(ModuleSymbol mod, boolean isSourceFile, String name) throws IOException {
+ Assert.checkNonNull(mod);
+
if (lint) {
int periodIndex = name.lastIndexOf(".");
if (periodIndex != -1) {
@@ -404,8 +451,12 @@
log.warning("proc.suspicious.class.name", name, extn);
}
}
- checkNameAndExistence(name, isSourceFile);
+ checkNameAndExistence(mod, name, isSourceFile);
Location loc = (isSourceFile ? SOURCE_OUTPUT : CLASS_OUTPUT);
+
+ if (modules.multiModuleMode) {
+ loc = this.fileManager.getLocationForModule(loc, mod.name.toString());
+ }
JavaFileObject.Kind kind = (isSourceFile ?
JavaFileObject.Kind.SOURCE :
JavaFileObject.Kind.CLASS);
@@ -418,21 +469,30 @@
log.warning("proc.file.create.last.round", name);
if (isSourceFile)
- aggregateGeneratedSourceNames.add(name);
+ aggregateGeneratedSourceNames.add(Pair.of(mod, name));
else
- aggregateGeneratedClassNames.add(name);
+ aggregateGeneratedClassNames.add(Pair.of(mod, name));
openTypeNames.add(name);
- return new FilerOutputJavaFileObject(name, fileObject);
+ return new FilerOutputJavaFileObject(mod, name, fileObject);
}
- @DefinedBy(Api.ANNOTATION_PROCESSING)
+ @Override @DefinedBy(Api.ANNOTATION_PROCESSING)
public FileObject createResource(JavaFileManager.Location location,
- CharSequence pkg,
+ CharSequence moduleAndPkg,
CharSequence relativeName,
Element... originatingElements) throws IOException {
+ Pair<ModuleSymbol, String> moduleAndPackage = checkOrInferModule(moduleAndPkg);
+ ModuleSymbol msym = moduleAndPackage.fst;
+ String pkg = moduleAndPackage.snd;
+
locationCheck(location);
+ if (modules.multiModuleMode) {
+ Assert.checkNonNull(msym);
+ location = this.fileManager.getLocationForModule(location, msym.name.toString());
+ }
+
String strPkg = pkg.toString();
if (strPkg.length() > 0)
checkName(strPkg);
@@ -443,9 +503,9 @@
checkFileReopening(fileObject, true);
if (fileObject instanceof JavaFileObject)
- return new FilerOutputJavaFileObject(null, (JavaFileObject)fileObject);
+ return new FilerOutputJavaFileObject(msym, null, (JavaFileObject)fileObject);
else
- return new FilerOutputFileObject(null, fileObject);
+ return new FilerOutputFileObject(msym, null, fileObject);
}
private void locationCheck(JavaFileManager.Location location) {
@@ -457,13 +517,21 @@
}
}
- @DefinedBy(Api.ANNOTATION_PROCESSING)
+ @Override @DefinedBy(Api.ANNOTATION_PROCESSING)
public FileObject getResource(JavaFileManager.Location location,
- CharSequence pkg,
+ CharSequence moduleAndPkg,
CharSequence relativeName) throws IOException {
- String strPkg = pkg.toString();
- if (strPkg.length() > 0)
- checkName(strPkg);
+ Pair<ModuleSymbol, String> moduleAndPackage = checkOrInferModule(moduleAndPkg);
+ ModuleSymbol msym = moduleAndPackage.fst;
+ String pkg = moduleAndPackage.snd;
+
+ if (modules.multiModuleMode) {
+ Assert.checkNonNull(msym);
+ location = this.fileManager.getLocationForModule(location, msym.name.toString());
+ }
+
+ if (pkg.length() > 0)
+ checkName(pkg);
// TODO: Only support reading resources in selected output
// locations? Only allow reading of non-source, non-class
@@ -478,12 +546,12 @@
FileObject fileObject;
if (location.isOutputLocation()) {
fileObject = fileManager.getFileForOutput(location,
- pkg.toString(),
+ pkg,
relativeName.toString(),
null);
} else {
fileObject = fileManager.getFileForInput(location,
- pkg.toString(),
+ pkg,
relativeName.toString());
}
if (fileObject == null) {
@@ -524,16 +592,19 @@
}
}
- private void checkNameAndExistence(String typename, boolean allowUnnamedPackageInfo) throws FilerException {
+ private void checkNameAndExistence(ModuleSymbol mod, String typename, boolean allowUnnamedPackageInfo) throws FilerException {
// TODO: Check if type already exists on source or class path?
// If so, use warning message key proc.type.already.exists
checkName(typename, allowUnnamedPackageInfo);
- if (aggregateGeneratedSourceNames.contains(typename) ||
- aggregateGeneratedClassNames.contains(typename)) {
+ if (aggregateGeneratedSourceNames.contains(Pair.of(mod, typename)) ||
+ aggregateGeneratedClassNames.contains(Pair.of(mod, typename))) {
if (lint)
log.warning("proc.type.recreate", typename);
throw new FilerException("Attempt to recreate a file for type " + typename);
}
+ if (!mod.isUnnamed() && !typename.contains(".")) {
+ throw new FilerException("Attempt to create a type in unnamed package of a named module: " + typename);
+ }
}
/**
@@ -565,7 +636,7 @@
return generatedSourceFileObjects;
}
- public Map<String, JavaFileObject> getGeneratedClasses() {
+ public Map<ModuleSymbol, Map<String, JavaFileObject>> getGeneratedClasses() {
return generatedClasses;
}
@@ -621,7 +692,7 @@
* Upon close, register files opened by create{Source, Class}File
* for annotation processing.
*/
- private void closeFileObject(String typeName, FileObject fileObject) {
+ private void closeFileObject(ModuleSymbol mod, String typeName, FileObject fileObject) {
/*
* If typeName is non-null, the file object was opened as a
* source or class file by the user. If a file was opened as
@@ -640,7 +711,7 @@
break;
case CLASS:
- generatedClasses.put(typeName, javaFileObject);
+ generatedClasses.computeIfAbsent(mod, m -> Collections.synchronizedMap(new LinkedHashMap<>())).put(typeName, javaFileObject);
openTypeNames.remove(typeName);
break;