mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 02:54:35 +02:00
8144226: Sjavac's handling of include/exclude patterns is buggy, redundant and inconsistent
Rewrote sjavac include/exclude pattern handling. Reviewed-by: jlahoda
This commit is contained in:
parent
180c59d147
commit
b345518d32
17 changed files with 462 additions and 522 deletions
|
@ -26,11 +26,20 @@
|
||||||
package com.sun.tools.sjavac;
|
package com.sun.tools.sjavac;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.FileVisitResult;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.PathMatcher;
|
||||||
|
import java.nio.file.SimpleFileVisitor;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
|
||||||
/** A Source object maintains information about a source file.
|
/** A Source object maintains information about a source file.
|
||||||
* For example which package it belongs to and kind of source it is.
|
* For example which package it belongs to and kind of source it is.
|
||||||
|
@ -56,8 +65,6 @@ public class Source implements Comparable<Source> {
|
||||||
private long lastModified;
|
private long lastModified;
|
||||||
// The source File.
|
// The source File.
|
||||||
private File file;
|
private File file;
|
||||||
// The source root under which file resides.
|
|
||||||
private File root;
|
|
||||||
// If the source is generated.
|
// If the source is generated.
|
||||||
private boolean isGenerated;
|
private boolean isGenerated;
|
||||||
// If the source is only linked to, not compiled.
|
// If the source is only linked to, not compiled.
|
||||||
|
@ -78,7 +85,7 @@ public class Source implements Comparable<Source> {
|
||||||
return name.hashCode();
|
return name.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Source(Module m, String n, File f, File r) {
|
public Source(Module m, String n, File f) {
|
||||||
name = n;
|
name = n;
|
||||||
int dp = n.lastIndexOf(".");
|
int dp = n.lastIndexOf(".");
|
||||||
if (dp != -1) {
|
if (dp != -1) {
|
||||||
|
@ -87,7 +94,6 @@ public class Source implements Comparable<Source> {
|
||||||
suffix = "";
|
suffix = "";
|
||||||
}
|
}
|
||||||
file = f;
|
file = f;
|
||||||
root = r;
|
|
||||||
lastModified = f.lastModified();
|
lastModified = f.lastModified();
|
||||||
linkedOnly = false;
|
linkedOnly = false;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +108,6 @@ public class Source implements Comparable<Source> {
|
||||||
suffix = "";
|
suffix = "";
|
||||||
}
|
}
|
||||||
file = null;
|
file = null;
|
||||||
root = null;
|
|
||||||
lastModified = lm;
|
lastModified = lm;
|
||||||
linkedOnly = false;
|
linkedOnly = false;
|
||||||
int ls = n.lastIndexOf('/');
|
int ls = n.lastIndexOf('/');
|
||||||
|
@ -112,7 +117,6 @@ public class Source implements Comparable<Source> {
|
||||||
public String suffix() { return suffix; }
|
public String suffix() { return suffix; }
|
||||||
public Package pkg() { return pkg; }
|
public Package pkg() { return pkg; }
|
||||||
public File file() { return file; }
|
public File file() { return file; }
|
||||||
public File root() { return root; }
|
|
||||||
public long lastModified() {
|
public long lastModified() {
|
||||||
return lastModified;
|
return lastModified;
|
||||||
}
|
}
|
||||||
|
@ -183,225 +187,122 @@ public class Source implements Comparable<Source> {
|
||||||
*/
|
*/
|
||||||
static public void scanRoot(File root,
|
static public void scanRoot(File root,
|
||||||
Set<String> suffixes,
|
Set<String> suffixes,
|
||||||
List<String> excludes, List<String> includes,
|
List<String> excludes,
|
||||||
List<String> excludeFiles, List<String> includeFiles,
|
List<String> includes,
|
||||||
Map<String,Source> foundFiles,
|
Map<String,Source> foundFiles,
|
||||||
Map<String,Module> foundModules,
|
Map<String,Module> foundModules,
|
||||||
Module currentModule,
|
final Module currentModule,
|
||||||
boolean permitSourcesWithoutPackage,
|
boolean permitSourcesWithoutPackage,
|
||||||
boolean inGensrc,
|
boolean inGensrc,
|
||||||
boolean inLinksrc)
|
boolean inLinksrc)
|
||||||
throws ProblemException {
|
throws IOException, ProblemException {
|
||||||
|
|
||||||
if (root == null) return;
|
if (root == null)
|
||||||
int root_prefix = root.getPath().length()+1;
|
return;
|
||||||
// This is the root source directory, it must not contain any Java sources files
|
|
||||||
// because we do not allow Java source files without a package.
|
|
||||||
// (Unless of course --permit-sources-without-package has been specified.)
|
|
||||||
// It might contain other source files however, (for -tr and -copy) these will
|
|
||||||
// always be included, since no package pattern can match the root directory.
|
|
||||||
currentModule = addFilesInDir(root, root_prefix, root, suffixes, permitSourcesWithoutPackage,
|
|
||||||
excludeFiles, includeFiles,
|
|
||||||
foundFiles, foundModules, currentModule,
|
|
||||||
inGensrc, inLinksrc);
|
|
||||||
|
|
||||||
File[] dirfiles = root.listFiles();
|
FileSystem fs = root.toPath().getFileSystem();
|
||||||
for (File d : dirfiles) {
|
|
||||||
if (d.isDirectory()) {
|
if (includes.isEmpty()) {
|
||||||
// Descend into the directory structure.
|
includes = Collections.singletonList("**");
|
||||||
scanDirectory(d, root_prefix, root, suffixes,
|
|
||||||
excludes, includes, excludeFiles, includeFiles,
|
|
||||||
foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
List<PathMatcher> includeMatchers = createPathMatchers(fs, includes);
|
||||||
* Test if a path matches any of the patterns given.
|
List<PathMatcher> excludeMatchers = createPathMatchers(fs, excludes);
|
||||||
* The pattern foo/bar matches only foo/bar
|
|
||||||
* The pattern foo/* matches foo/bar and foo/bar/zoo etc
|
|
||||||
*/
|
|
||||||
static private boolean hasMatch(String path, List<String> patterns) {
|
|
||||||
|
|
||||||
// Convert Windows '\' to '/' for the sake of comparing with the patterns
|
Files.walkFileTree(root.toPath(), new SimpleFileVisitor<Path>() {
|
||||||
path = path.replace(File.separatorChar, '/');
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
|
|
||||||
for (String p : patterns) {
|
Path relToRoot = root.toPath().relativize(file);
|
||||||
// Exact match
|
|
||||||
if (p.equals(path))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Single dot the end matches this package and all its subpackages.
|
if (includeMatchers.stream().anyMatch(im -> im.matches(relToRoot))
|
||||||
if (p.endsWith("/*")) {
|
&& excludeMatchers.stream().noneMatch(em -> em.matches(relToRoot))
|
||||||
// Remove the wildcard
|
&& suffixes.contains(Util.fileSuffix(file))) {
|
||||||
String patprefix = p.substring(0,p.length()-2);
|
|
||||||
// Does the path start with the pattern prefix?
|
|
||||||
if (path.startsWith(patprefix)) {
|
|
||||||
// If the path has the same length as the pattern prefix, then it is a match.
|
|
||||||
// If the path is longer, then make sure that
|
|
||||||
// the next part of the path starts with a dot (.) to prevent
|
|
||||||
// wildcard matching in the middle of a package name.
|
|
||||||
if (path.length()==patprefix.length() || path.charAt(patprefix.length())=='/') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// TODO: Test this.
|
||||||
* Matches patterns with the asterisk first. */
|
Source existing = foundFiles.get(file);
|
||||||
// The pattern foo/bar.java only matches foo/bar.java
|
if (existing != null) {
|
||||||
// The pattern */bar.java matches foo/bar.java and zoo/bar.java etc
|
throw new IOException("You have already added the file "+file+" from "+existing.file().getPath());
|
||||||
static private boolean hasFileMatch(String path, List<String> patterns) {
|
}
|
||||||
// Convert Windows '\' to '/' for the sake of comparing with the patterns
|
existing = currentModule.lookupSource(file.toString());
|
||||||
path = path.replace(File.separatorChar, '/');
|
if (existing != null) {
|
||||||
|
|
||||||
path = Util.normalizeDriveLetter(path);
|
|
||||||
for (String p : patterns) {
|
|
||||||
// Exact match
|
|
||||||
if (p.equals(path)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Single dot the end matches this package and all its subpackages.
|
|
||||||
if (p.startsWith("*")) {
|
|
||||||
// Remove the wildcard
|
|
||||||
String patsuffix = p.substring(1);
|
|
||||||
// Does the path start with the pattern prefix?
|
|
||||||
if (path.endsWith(patsuffix)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the files in the directory, assuming that the file has not been excluded.
|
|
||||||
* Returns a fresh Module object, if this was a dir with a module-info.java file.
|
|
||||||
*/
|
|
||||||
static private Module addFilesInDir(File dir, int rootPrefix, File root,
|
|
||||||
Set<String> suffixes, boolean allow_javas,
|
|
||||||
List<String> excludeFiles, List<String> includeFiles,
|
|
||||||
Map<String,Source> foundFiles,
|
|
||||||
Map<String,Module> foundModules,
|
|
||||||
Module currentModule,
|
|
||||||
boolean inGensrc,
|
|
||||||
boolean inLinksrc)
|
|
||||||
throws ProblemException
|
|
||||||
{
|
|
||||||
for (File f : dir.listFiles()) {
|
|
||||||
|
|
||||||
if (!f.isFile())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
boolean should_add =
|
|
||||||
(excludeFiles == null || excludeFiles.isEmpty() || !hasFileMatch(f.getPath(), excludeFiles))
|
|
||||||
&& (includeFiles == null || includeFiles.isEmpty() || hasFileMatch(f.getPath(), includeFiles));
|
|
||||||
|
|
||||||
if (!should_add)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!allow_javas && f.getName().endsWith(".java")) {
|
|
||||||
throw new ProblemException("No .java files are allowed in the source root "+dir.getPath()+
|
|
||||||
", please remove "+f.getName());
|
|
||||||
}
|
|
||||||
// Extract the file name relative the root.
|
|
||||||
String fn = f.getPath().substring(rootPrefix);
|
|
||||||
// Extract the package name.
|
|
||||||
int sp = fn.lastIndexOf(File.separatorChar);
|
|
||||||
String pkg = "";
|
|
||||||
if (sp != -1) {
|
|
||||||
pkg = fn.substring(0,sp).replace(File.separatorChar,'.');
|
|
||||||
}
|
|
||||||
// Is this a module-info.java file?
|
|
||||||
if (fn.endsWith("module-info.java")) {
|
|
||||||
// Aha! We have recursed into a module!
|
|
||||||
if (!currentModule.name().equals("")) {
|
|
||||||
throw new ProblemException("You have an extra module-info.java inside a module! Please remove "+fn);
|
|
||||||
}
|
|
||||||
String module_name = fn.substring(0,fn.length()-16);
|
|
||||||
currentModule = new Module(module_name, f.getPath());
|
|
||||||
foundModules.put(module_name, currentModule);
|
|
||||||
}
|
|
||||||
// Extract the suffix.
|
|
||||||
int dp = fn.lastIndexOf(".");
|
|
||||||
String suffix = "";
|
|
||||||
if (dp > 0) {
|
|
||||||
suffix = fn.substring(dp);
|
|
||||||
}
|
|
||||||
// Should the file be added?
|
|
||||||
if (suffixes.contains(suffix)) {
|
|
||||||
Source of = foundFiles.get(f.getPath());
|
|
||||||
if (of != null) {
|
|
||||||
throw new ProblemException("You have already added the file "+fn+" from "+of.file().getPath());
|
|
||||||
}
|
|
||||||
of = currentModule.lookupSource(f.getPath());
|
|
||||||
if (of != null) {
|
|
||||||
// Oups, the source is already added, could be ok, could be not, lets check.
|
// Oups, the source is already added, could be ok, could be not, lets check.
|
||||||
if (inLinksrc) {
|
if (inLinksrc) {
|
||||||
// So we are collecting sources for linking only.
|
// So we are collecting sources for linking only.
|
||||||
if (of.isLinkedOnly()) {
|
if (existing.isLinkedOnly()) {
|
||||||
// Ouch, this one is also for linking only. Bad.
|
// Ouch, this one is also for linking only. Bad.
|
||||||
throw new ProblemException("You have already added the link only file "+fn+" from "+of.file().getPath());
|
throw new IOException("You have already added the link only file " + file + " from " + existing.file().getPath());
|
||||||
}
|
}
|
||||||
// Ok, the existing source is to be compiled. Thus this link only is redundant
|
// Ok, the existing source is to be compiled. Thus this link only is redundant
|
||||||
// since all compiled are also linked to. Continue to the next source.
|
// since all compiled are also linked to. Continue to the next source.
|
||||||
// But we need to add the source, so that it will be visible to linking,
|
// But we need to add the source, so that it will be visible to linking,
|
||||||
// if not the multi core compile will fail because a JavaCompiler cannot
|
// if not the multi core compile will fail because a JavaCompiler cannot
|
||||||
// find the necessary dependencies for its part of the source.
|
// find the necessary dependencies for its part of the source.
|
||||||
foundFiles.put(f.getPath(), of);
|
foundFiles.put(file.toString(), existing);
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
// We are looking for sources to compile, if we find an existing to be compiled
|
// We are looking for sources to compile, if we find an existing to be compiled
|
||||||
// source with the same name, it is an internal error, since we must
|
// source with the same name, it is an internal error, since we must
|
||||||
// find the sources to be compiled before we find the sources to be linked to.
|
// find the sources to be compiled before we find the sources to be linked to.
|
||||||
throw new ProblemException("Internal error: Double add of file "+fn+" from "+of.file().getPath());
|
throw new IOException("Internal error: Double add of file " + file + " from " + existing.file().getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
// Add source
|
||||||
|
Source s = new Source(currentModule, file.toString(), file.toFile());
|
||||||
|
if (inGensrc) {
|
||||||
|
s.markAsGenerated();
|
||||||
}
|
}
|
||||||
Source s = new Source(currentModule, f.getPath(), f, root);
|
|
||||||
if (inGensrc) s.markAsGenerated();
|
|
||||||
if (inLinksrc) {
|
if (inLinksrc) {
|
||||||
s.markAsLinkedOnly();
|
s.markAsLinkedOnly();
|
||||||
}
|
}
|
||||||
|
String pkg = packageOfJavaFile(root.toPath(), file);
|
||||||
pkg = currentModule.name() + ":" + pkg;
|
pkg = currentModule.name() + ":" + pkg;
|
||||||
foundFiles.put(f.getPath(), s);
|
foundFiles.put(file.toString(), s);
|
||||||
currentModule.addSource(pkg, s);
|
currentModule.addSource(pkg, s);
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return currentModule;
|
|
||||||
}
|
|
||||||
|
|
||||||
static private void scanDirectory(File dir, int rootPrefix, File root,
|
return FileVisitResult.CONTINUE;
|
||||||
Set<String> suffixes,
|
|
||||||
List<String> excludes, List<String> includes,
|
|
||||||
List<String> excludeFiles, List<String> includeFiles,
|
|
||||||
Map<String,Source> foundFiles,
|
|
||||||
Map<String,Module> foundModules,
|
|
||||||
Module currentModule, boolean inGensrc, boolean inLinksrc)
|
|
||||||
throws ProblemException {
|
|
||||||
|
|
||||||
String path = "";
|
|
||||||
// Remove the root prefix from the dir path
|
|
||||||
if (dir.getPath().length() > rootPrefix) {
|
|
||||||
path = dir.getPath().substring(rootPrefix);
|
|
||||||
}
|
}
|
||||||
// Should this package directory be included and not excluded?
|
});
|
||||||
if ((includes==null || includes.isEmpty() || hasMatch(path, includes)) &&
|
|
||||||
(excludes==null || excludes.isEmpty() || !hasMatch(path, excludes))) {
|
|
||||||
// Add the source files.
|
|
||||||
currentModule = addFilesInDir(dir, rootPrefix, root, suffixes, true, excludeFiles, includeFiles,
|
|
||||||
foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (File d : dir.listFiles()) {
|
private static List<PathMatcher> createPathMatchers(FileSystem fs, List<String> patterns) {
|
||||||
if (d.isDirectory()) {
|
List<PathMatcher> matchers = new ArrayList<>();
|
||||||
// Descend into the directory structure.
|
for (String pattern : patterns) {
|
||||||
scanDirectory(d, rootPrefix, root, suffixes,
|
try {
|
||||||
excludes, includes, excludeFiles, includeFiles,
|
matchers.add(fs.getPathMatcher("glob:" + pattern));
|
||||||
foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
|
} catch (PatternSyntaxException e) {
|
||||||
|
Log.error("Invalid pattern: " + pattern);
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return matchers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String packageOfJavaFile(Path sourceRoot, Path javaFile) {
|
||||||
|
Path javaFileDir = javaFile.getParent();
|
||||||
|
Path packageDir = sourceRoot.relativize(javaFileDir);
|
||||||
|
List<String> separateDirs = new ArrayList<>();
|
||||||
|
for (Path pathElement : packageDir) {
|
||||||
|
separateDirs.add(pathElement.getFileName().toString());
|
||||||
|
}
|
||||||
|
return String.join(".", separateDirs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s[pkg: %s, name: %s, suffix: %s, file: %s, isGenerated: %b, linkedOnly: %b]",
|
||||||
|
getClass().getSimpleName(),
|
||||||
|
pkg,
|
||||||
|
name,
|
||||||
|
suffix,
|
||||||
|
file,
|
||||||
|
isGenerated,
|
||||||
|
linkedOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,4 +230,10 @@ public class Util {
|
||||||
Function<? super T, ? extends I> indexFunction) {
|
Function<? super T, ? extends I> indexFunction) {
|
||||||
return c.stream().collect(Collectors.<T, I, T>toMap(indexFunction, o -> o));
|
return c.stream().collect(Collectors.<T, I, T>toMap(indexFunction, o -> o));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String fileSuffix(Path file) {
|
||||||
|
String fileNameStr = file.getFileName().toString();
|
||||||
|
int dotIndex = fileNameStr.indexOf('.');
|
||||||
|
return dotIndex == -1 ? "" : fileNameStr.substring(dotIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,7 @@ public class SjavacImpl implements Sjavac {
|
||||||
Module current_module = new Module("", "");
|
Module current_module = new Module("", "");
|
||||||
modules.put("", current_module);
|
modules.put("", current_module);
|
||||||
|
|
||||||
|
try {
|
||||||
// Find all sources, use the suffix rules to know which files are sources.
|
// Find all sources, use the suffix rules to know which files are sources.
|
||||||
Map<String,Source> sources = new HashMap<>();
|
Map<String,Source> sources = new HashMap<>();
|
||||||
|
|
||||||
|
@ -214,7 +215,6 @@ public class SjavacImpl implements Sjavac {
|
||||||
// Go through all sources and taint all packages that miss artifacts.
|
// Go through all sources and taint all packages that miss artifacts.
|
||||||
javac_state.taintPackagesThatMissArtifacts();
|
javac_state.taintPackagesThatMissArtifacts();
|
||||||
|
|
||||||
try {
|
|
||||||
// Check recorded classpath public apis. Taint packages that depend on
|
// Check recorded classpath public apis. Taint packages that depend on
|
||||||
// classpath classes whose public apis have changed.
|
// classpath classes whose public apis have changed.
|
||||||
javac_state.taintPackagesDependingOnChangedClasspathPackages();
|
javac_state.taintPackagesDependingOnChangedClasspathPackages();
|
||||||
|
@ -229,8 +229,16 @@ public class SjavacImpl implements Sjavac {
|
||||||
// (Generated sources must always have a package.)
|
// (Generated sources must always have a package.)
|
||||||
Map<String,Source> generated_sources = new HashMap<>();
|
Map<String,Source> generated_sources = new HashMap<>();
|
||||||
|
|
||||||
Source.scanRoot(Util.pathToFile(options.getGenSrcDir()), Util.set(".java"), null, null, null, null,
|
Source.scanRoot(Util.pathToFile(options.getGenSrcDir()),
|
||||||
generated_sources, modules, current_module, false, true, false);
|
Util.set(".java"),
|
||||||
|
Collections.emptyList(),
|
||||||
|
Collections.emptyList(),
|
||||||
|
generated_sources,
|
||||||
|
modules,
|
||||||
|
current_module,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false);
|
||||||
javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
|
javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
|
||||||
// Recheck the the source files and their timestamps again.
|
// Recheck the the source files and their timestamps again.
|
||||||
javac_state.checkSourceStatus(true);
|
javac_state.checkSourceStatus(true);
|
||||||
|
@ -254,7 +262,10 @@ public class SjavacImpl implements Sjavac {
|
||||||
printRound(round);
|
printRound(round);
|
||||||
// Clean out artifacts in tainted packages.
|
// Clean out artifacts in tainted packages.
|
||||||
javac_state.deleteClassArtifactsInTaintedPackages();
|
javac_state.deleteClassArtifactsInTaintedPackages();
|
||||||
again = javac_state.performJavaCompilations(compilationService, options, recently_compiled, rc);
|
again = javac_state.performJavaCompilations(compilationService,
|
||||||
|
options,
|
||||||
|
recently_compiled,
|
||||||
|
rc);
|
||||||
if (!rc[0]) {
|
if (!rc[0]) {
|
||||||
Log.debug("Compilation failed.");
|
Log.debug("Compilation failed.");
|
||||||
break;
|
break;
|
||||||
|
@ -344,7 +355,8 @@ public class SjavacImpl implements Sjavac {
|
||||||
Map<String, Module> foundModules,
|
Map<String, Module> foundModules,
|
||||||
Module currentModule,
|
Module currentModule,
|
||||||
boolean permitSourcesInDefaultPackage,
|
boolean permitSourcesInDefaultPackage,
|
||||||
boolean inLinksrc) {
|
boolean inLinksrc)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
for (SourceLocation source : sourceLocations) {
|
for (SourceLocation source : sourceLocations) {
|
||||||
source.findSourceFiles(sourceTypes,
|
source.findSourceFiles(sourceTypes,
|
||||||
|
|
|
@ -93,7 +93,7 @@ public enum Option {
|
||||||
CLASSPATH.processMatching(iter, helper);
|
CLASSPATH.processMatching(iter, helper);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
X("-x", "Exclude directory from the subsequent source directory") {
|
X("-x", "Exclude files matching the given pattern") {
|
||||||
@Override
|
@Override
|
||||||
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
|
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
|
||||||
String pattern = getFilePatternArg(iter, helper);
|
String pattern = getFilePatternArg(iter, helper);
|
||||||
|
@ -101,7 +101,7 @@ public enum Option {
|
||||||
helper.exclude(pattern);
|
helper.exclude(pattern);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
I("-i", "Include only the given directory from the subsequent source directory") {
|
I("-i", "Include only files matching the given pattern") {
|
||||||
@Override
|
@Override
|
||||||
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
|
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
|
||||||
String pattern = getFilePatternArg(iter, helper);
|
String pattern = getFilePatternArg(iter, helper);
|
||||||
|
@ -109,22 +109,6 @@ public enum Option {
|
||||||
helper.include(pattern);
|
helper.include(pattern);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
XF("-xf", "Exclude a given file") {
|
|
||||||
@Override
|
|
||||||
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
|
|
||||||
String pattern = getFilePatternArg(iter, helper);
|
|
||||||
if (pattern != null)
|
|
||||||
helper.excludeFile(pattern);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
IF("-if", "Include only the given file") {
|
|
||||||
@Override
|
|
||||||
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
|
|
||||||
String pattern = getFilePatternArg(iter, helper);
|
|
||||||
if (pattern != null)
|
|
||||||
helper.includeFile(pattern);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
TR("-tr", "Translate resources") {
|
TR("-tr", "Translate resources") {
|
||||||
@Override
|
@Override
|
||||||
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
|
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
|
||||||
|
@ -338,7 +322,7 @@ public enum Option {
|
||||||
String getFilePatternArg(ArgumentIterator iter, OptionHelper helper) {
|
String getFilePatternArg(ArgumentIterator iter, OptionHelper helper) {
|
||||||
|
|
||||||
if (!iter.hasNext()) {
|
if (!iter.hasNext()) {
|
||||||
helper.reportError(arg + " must be followed by a file or directory pattern.");
|
helper.reportError(arg + " must be followed by a glob pattern.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,12 +53,6 @@ public abstract class OptionHelper {
|
||||||
/** Record a package inclusion pattern */
|
/** Record a package inclusion pattern */
|
||||||
public abstract void include(String incl);
|
public abstract void include(String incl);
|
||||||
|
|
||||||
/** Record a file exclusion */
|
|
||||||
public abstract void excludeFile(String exclFile);
|
|
||||||
|
|
||||||
/** Record a file inclusion */
|
|
||||||
public abstract void includeFile(String inclFile);
|
|
||||||
|
|
||||||
/** Record a root of sources to be compiled */
|
/** Record a root of sources to be compiled */
|
||||||
public abstract void sourceRoots(List<Path> path);
|
public abstract void sourceRoots(List<Path> path);
|
||||||
|
|
||||||
|
|
|
@ -220,8 +220,6 @@ public class Options {
|
||||||
for (SourceLocation sl : locs) {
|
for (SourceLocation sl : locs) {
|
||||||
for (String pkg : sl.includes) addArg(Option.I, pkg);
|
for (String pkg : sl.includes) addArg(Option.I, pkg);
|
||||||
for (String pkg : sl.excludes) addArg(Option.X, pkg);
|
for (String pkg : sl.excludes) addArg(Option.X, pkg);
|
||||||
for (String f : sl.excludedFiles) addArg(Option.XF, f);
|
|
||||||
for (String f : sl.includedFiles) addArg(Option.IF, f);
|
|
||||||
addArg(opt, sl.getPath());
|
addArg(opt, sl.getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,18 +377,6 @@ public class Options {
|
||||||
includes.add(inclPattern);
|
includes.add(inclPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void excludeFile(String exclFilePattern) {
|
|
||||||
exclFilePattern = Util.normalizeDriveLetter(exclFilePattern);
|
|
||||||
excludeFiles.add(exclFilePattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void includeFile(String inclFilePattern) {
|
|
||||||
inclFilePattern = Util.normalizeDriveLetter(inclFilePattern);
|
|
||||||
includeFiles.add(inclFilePattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTransformer(String suffix, Transformer tr) {
|
public void addTransformer(String suffix, Transformer tr) {
|
||||||
if (trRules.containsKey(suffix)) {
|
if (trRules.containsKey(suffix)) {
|
||||||
|
@ -519,9 +505,7 @@ public class Options {
|
||||||
result.add(new SourceLocation(
|
result.add(new SourceLocation(
|
||||||
path,
|
path,
|
||||||
includes,
|
includes,
|
||||||
excludes,
|
excludes));
|
||||||
includeFiles,
|
|
||||||
excludeFiles));
|
|
||||||
}
|
}
|
||||||
resetFilters();
|
resetFilters();
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -25,11 +25,13 @@
|
||||||
|
|
||||||
package com.sun.tools.sjavac.options;
|
package com.sun.tools.sjavac.options;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.sun.tools.sjavac.Log;
|
||||||
import com.sun.tools.sjavac.Module;
|
import com.sun.tools.sjavac.Module;
|
||||||
import com.sun.tools.sjavac.ProblemException;
|
import com.sun.tools.sjavac.ProblemException;
|
||||||
import com.sun.tools.sjavac.Source;
|
import com.sun.tools.sjavac.Source;
|
||||||
|
@ -49,18 +51,14 @@ public class SourceLocation {
|
||||||
private Path path;
|
private Path path;
|
||||||
|
|
||||||
// Package include / exclude patterns and file includes / excludes.
|
// Package include / exclude patterns and file includes / excludes.
|
||||||
List<String> includes, excludes, includedFiles, excludedFiles;
|
List<String> includes, excludes;
|
||||||
|
|
||||||
public SourceLocation(Path path,
|
public SourceLocation(Path path,
|
||||||
List<String> includes,
|
List<String> includes,
|
||||||
List<String> excludes,
|
List<String> excludes) {
|
||||||
List<String> includedFiles,
|
|
||||||
List<String> excludedFiles) {
|
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.includes = includes;
|
this.includes = includes;
|
||||||
this.excludes = excludes;
|
this.excludes = excludes;
|
||||||
this.includedFiles = includedFiles;
|
|
||||||
this.excludedFiles = excludedFiles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,17 +79,23 @@ public class SourceLocation {
|
||||||
Map<String, Module> foundModules,
|
Map<String, Module> foundModules,
|
||||||
Module currentModule,
|
Module currentModule,
|
||||||
boolean permitSourcesInDefaultPackage,
|
boolean permitSourcesInDefaultPackage,
|
||||||
boolean inLinksrc) {
|
boolean inLinksrc)
|
||||||
|
throws IOException {
|
||||||
try {
|
try {
|
||||||
Source.scanRoot(path.toFile(), suffixes, excludes, includes,
|
Source.scanRoot(path.toFile(),
|
||||||
excludedFiles, includedFiles, foundFiles, foundModules,
|
suffixes,
|
||||||
currentModule, permitSourcesInDefaultPackage, false,
|
excludes,
|
||||||
|
includes,
|
||||||
|
foundFiles,
|
||||||
|
foundModules,
|
||||||
|
currentModule,
|
||||||
|
permitSourcesInDefaultPackage,
|
||||||
|
false,
|
||||||
inLinksrc);
|
inLinksrc);
|
||||||
} catch (ProblemException e) {
|
} catch (ProblemException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the root directory of this source location */
|
/** Get the root directory of this source location */
|
||||||
public Path getPath() {
|
public Path getPath() {
|
||||||
return path;
|
return path;
|
||||||
|
@ -107,14 +111,9 @@ public class SourceLocation {
|
||||||
return excludes;
|
return excludes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the file include patterns */
|
@Override
|
||||||
public List<String> getIncludedFiles() {
|
public String toString() {
|
||||||
return includedFiles;
|
return String.format("%s[\"%s\", includes: %s, excludes: %s]",
|
||||||
|
getClass().getSimpleName(), path, includes, excludes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the file exclude patterns */
|
|
||||||
public List<String> getExcludedFiles() {
|
|
||||||
return excludedFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,9 +55,9 @@ public class CompileExcludingDependency extends SJavacTester {
|
||||||
tb.writeFile(GENSRC.resolve("beta/B.java"),
|
tb.writeFile(GENSRC.resolve("beta/B.java"),
|
||||||
"package beta; public class B { }");
|
"package beta; public class B { }");
|
||||||
|
|
||||||
compile("-x", "beta",
|
compile("-x", "beta/*",
|
||||||
"-src", GENSRC.toString(),
|
"-src", GENSRC.toString(),
|
||||||
"-x", "alfa/omega",
|
"-x", "alfa/omega/*",
|
||||||
"-sourcepath", GENSRC.toString(),
|
"-sourcepath", GENSRC.toString(),
|
||||||
"-d", BIN.toString(),
|
"-d", BIN.toString(),
|
||||||
"--state-dir=" + BIN,
|
"--state-dir=" + BIN,
|
||||||
|
|
|
@ -47,8 +47,8 @@ public class CompileWithAtFile extends SJavacTester {
|
||||||
|
|
||||||
void test() throws Exception {
|
void test() throws Exception {
|
||||||
tb.writeFile(GENSRC.resolve("list.txt"),
|
tb.writeFile(GENSRC.resolve("list.txt"),
|
||||||
"-if */alfa/omega/A.java\n" +
|
"-i alfa/omega/A.java\n" +
|
||||||
"-if */beta/B.java\n" +
|
"-i beta/B.java\n" +
|
||||||
GENSRC + "\n" +
|
GENSRC + "\n" +
|
||||||
"-d " + BIN + "\n" +
|
"-d " + BIN + "\n" +
|
||||||
"--state-dir=" + BIN + "\n");
|
"--state-dir=" + BIN + "\n");
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class CompileWithInvisibleSources extends SJavacTester {
|
||||||
"package beta; public class B { }");
|
"package beta; public class B { }");
|
||||||
|
|
||||||
compile(GENSRC.toString(),
|
compile(GENSRC.toString(),
|
||||||
"-x", "beta",
|
"-x", "beta/*",
|
||||||
"-sourcepath", GENSRC2.toString(),
|
"-sourcepath", GENSRC2.toString(),
|
||||||
"-sourcepath", GENSRC3.toString(),
|
"-sourcepath", GENSRC3.toString(),
|
||||||
"-d", BIN.toString(),
|
"-d", BIN.toString(),
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class CompileWithOverrideSources extends SJavacTester {
|
||||||
tb.writeFile(GENSRC2.resolve("beta/B.java"),
|
tb.writeFile(GENSRC2.resolve("beta/B.java"),
|
||||||
"package beta; public class B { }");
|
"package beta; public class B { }");
|
||||||
|
|
||||||
compile("-x", "beta",
|
compile("-x", "beta/*",
|
||||||
GENSRC.toString(),
|
GENSRC.toString(),
|
||||||
GENSRC2.toString(),
|
GENSRC2.toString(),
|
||||||
"-d", BIN.toString(),
|
"-d", BIN.toString(),
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @test
|
|
||||||
* @bug 8037085
|
|
||||||
* @summary Ensures that sjavac can handle various exclusion patterns.
|
|
||||||
*
|
|
||||||
* @modules jdk.compiler/com.sun.tools.sjavac
|
|
||||||
* @build Wrapper
|
|
||||||
* @run main Wrapper ExclPattern
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
public class ExclPattern {
|
|
||||||
|
|
||||||
public static void main(String[] ignore) throws IOException {
|
|
||||||
|
|
||||||
String toBeExcluded = "pkg/excl-dir/excluded.txt";
|
|
||||||
String toBeIncluded = "pkg/incl-dir/included.txt";
|
|
||||||
|
|
||||||
// Set up source directory with directory to be excluded
|
|
||||||
populate(Paths.get("srcdir"),
|
|
||||||
"pkg/SomeClass.java",
|
|
||||||
"package pkg; public class SomeClass { }",
|
|
||||||
|
|
||||||
toBeExcluded,
|
|
||||||
"This file should not end up in the dest directory.",
|
|
||||||
|
|
||||||
toBeIncluded,
|
|
||||||
"This file should end up in the dest directory.");
|
|
||||||
|
|
||||||
String[] args = {
|
|
||||||
"-x", "pkg/excl-dir/*",
|
|
||||||
"-src", "srcdir",
|
|
||||||
"-d", "dest",
|
|
||||||
"--state-dir=dest",
|
|
||||||
"-j", "1",
|
|
||||||
"-copy", ".txt",
|
|
||||||
"--server:portfile=testserver,background=false",
|
|
||||||
"--log=debug"
|
|
||||||
};
|
|
||||||
|
|
||||||
int rc = com.sun.tools.sjavac.Main.go(args);
|
|
||||||
if (rc != 0) throw new RuntimeException("Error during compile!");
|
|
||||||
|
|
||||||
if (!Files.exists(Paths.get("dest/" + toBeIncluded)))
|
|
||||||
throw new AssertionError("File missing: " + toBeIncluded);
|
|
||||||
|
|
||||||
if (Files.exists(Paths.get("dest/" + toBeExcluded)))
|
|
||||||
throw new AssertionError("File present: " + toBeExcluded);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void populate(Path root, String... args) throws IOException {
|
|
||||||
if (!Files.exists(root))
|
|
||||||
Files.createDirectory(root);
|
|
||||||
for (int i = 0; i < args.length; i += 2) {
|
|
||||||
String filename = args[i];
|
|
||||||
String content = args[i+1];
|
|
||||||
Path p = root.resolve(filename);
|
|
||||||
Files.createDirectories(p.getParent());
|
|
||||||
try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(p,
|
|
||||||
Charset.defaultCharset()))) {
|
|
||||||
out.println(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
67
langtools/test/tools/sjavac/HiddenFiles.java
Normal file
67
langtools/test/tools/sjavac/HiddenFiles.java
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8144226
|
||||||
|
* @summary Ensures that excluded files are inaccessible (even for implicit
|
||||||
|
* compilation)
|
||||||
|
*
|
||||||
|
* @modules jdk.compiler/com.sun.tools.sjavac
|
||||||
|
* @library /tools/lib
|
||||||
|
* @build Wrapper ToolBox
|
||||||
|
* @run main Wrapper HiddenFiles
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.sun.tools.javac.util.Assert;
|
||||||
|
import com.sun.tools.sjavac.server.Sjavac;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public class HiddenFiles extends SjavacBase {
|
||||||
|
|
||||||
|
public static void main(String[] ignore) throws Exception {
|
||||||
|
Path BIN = Paths.get("bin");
|
||||||
|
Path STATE_DIR = Paths.get("state-dir");
|
||||||
|
Path SRC = Paths.get("src");
|
||||||
|
|
||||||
|
Files.createDirectories(BIN);
|
||||||
|
Files.createDirectories(STATE_DIR);
|
||||||
|
|
||||||
|
toolbox.writeJavaFiles(SRC, "package pkg; class A { B b; }");
|
||||||
|
toolbox.writeJavaFiles(SRC, "package pkg; class B { }");
|
||||||
|
|
||||||
|
// This compilation should fail (return RC_FATAL) since A.java refers to B.java and B.java
|
||||||
|
// is excluded.
|
||||||
|
int rc = compile("-x", "pkg/B.java", SRC.toString(),
|
||||||
|
"--server:portfile=testportfile,background=false",
|
||||||
|
"-d", BIN.toString(),
|
||||||
|
"--state-dir=" + STATE_DIR);
|
||||||
|
|
||||||
|
Assert.check(rc == Sjavac.RC_FATAL, "Compilation succeeded unexpectedly.");
|
||||||
|
}
|
||||||
|
}
|
166
langtools/test/tools/sjavac/IncludeExcludePatterns.java
Normal file
166
langtools/test/tools/sjavac/IncludeExcludePatterns.java
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8037085
|
||||||
|
* @summary Ensures that sjavac can handle various exclusion patterns.
|
||||||
|
*
|
||||||
|
* @modules jdk.compiler/com.sun.tools.sjavac
|
||||||
|
* @library /tools/lib
|
||||||
|
* @build Wrapper ToolBox
|
||||||
|
* @run main Wrapper IncludeExcludePatterns
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.sun.tools.javac.util.Assert;
|
||||||
|
import com.sun.tools.sjavac.server.Sjavac;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class IncludeExcludePatterns extends SjavacBase {
|
||||||
|
|
||||||
|
final Path SRC = Paths.get("src");
|
||||||
|
final Path BIN = Paths.get("bin");
|
||||||
|
final Path STATE_DIR = Paths.get("state-dir");
|
||||||
|
|
||||||
|
// An arbitrarily but sufficiently complicated source tree.
|
||||||
|
final Path A = Paths.get("pkga/A.java");
|
||||||
|
final Path X1 = Paths.get("pkga/subpkg/Xx.java");
|
||||||
|
final Path Y = Paths.get("pkga/subpkg/subsubpkg/Y.java");
|
||||||
|
final Path B = Paths.get("pkgb/B.java");
|
||||||
|
final Path C = Paths.get("pkgc/C.java");
|
||||||
|
final Path X2 = Paths.get("pkgc/Xx.java");
|
||||||
|
|
||||||
|
final Path[] ALL_PATHS = {A, X1, Y, B, C, X2};
|
||||||
|
|
||||||
|
public static void main(String[] ignore) throws Exception {
|
||||||
|
new IncludeExcludePatterns().runTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runTest() throws IOException, ReflectiveOperationException {
|
||||||
|
Files.createDirectories(BIN);
|
||||||
|
Files.createDirectories(STATE_DIR);
|
||||||
|
for (Path p : ALL_PATHS) {
|
||||||
|
writeDummyClass(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single file
|
||||||
|
testPattern("pkga/A.java", A);
|
||||||
|
|
||||||
|
// Leading wild cards
|
||||||
|
testPattern("*/A.java", A);
|
||||||
|
testPattern("**/Xx.java", X1, X2);
|
||||||
|
testPattern("**x.java", X1, X2);
|
||||||
|
|
||||||
|
// Wild card in middle of path
|
||||||
|
testPattern("pkga/*/Xx.java", X1);
|
||||||
|
testPattern("pkga/**/Y.java", Y);
|
||||||
|
|
||||||
|
// Trailing wild cards
|
||||||
|
testPattern("pkga/*", A);
|
||||||
|
testPattern("pkga/**", A, X1, Y);
|
||||||
|
|
||||||
|
// Multiple wildcards
|
||||||
|
testPattern("pkga/*/*/Y.java", Y);
|
||||||
|
testPattern("**/*/**", X1, Y);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given "src/pkg/subpkg/A.java" this method returns "A"
|
||||||
|
String classNameOf(Path javaFile) {
|
||||||
|
return javaFile.getFileName()
|
||||||
|
.toString()
|
||||||
|
.replace(".java", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Puts an empty (dummy) class definition in the given path.
|
||||||
|
void writeDummyClass(Path javaFile) throws IOException {
|
||||||
|
String pkg = javaFile.getParent().toString().replace('/', '.');
|
||||||
|
String cls = javaFile.getFileName().toString().replace(".java", "");
|
||||||
|
toolbox.writeFile(SRC.resolve(javaFile), "package " + pkg + "; class " + cls + " {}");
|
||||||
|
}
|
||||||
|
|
||||||
|
void testPattern(String filterArgs, Path... sourcesExpectedToBeVisible)
|
||||||
|
throws ReflectiveOperationException, IOException {
|
||||||
|
testFilter("-i " + filterArgs, Arrays.asList(sourcesExpectedToBeVisible));
|
||||||
|
|
||||||
|
Set<Path> complement = new HashSet<>(Arrays.asList(ALL_PATHS));
|
||||||
|
complement.removeAll(Arrays.asList(sourcesExpectedToBeVisible));
|
||||||
|
testFilter("-x " + filterArgs, complement);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testFilter(String filterArgs, Collection<Path> sourcesExpectedToBeVisible)
|
||||||
|
throws IOException, ReflectiveOperationException {
|
||||||
|
System.out.println("Testing filter: " + filterArgs);
|
||||||
|
toolbox.cleanDirectory(BIN);
|
||||||
|
toolbox.cleanDirectory(STATE_DIR);
|
||||||
|
String args = filterArgs + " " + SRC
|
||||||
|
+ " --server:portfile=testportfile,background=false"
|
||||||
|
+ " -d " + BIN
|
||||||
|
+ " --state-dir=" + STATE_DIR;
|
||||||
|
int rc = compile((Object[]) args.split(" "));
|
||||||
|
|
||||||
|
// Compilation should always pass in these tests
|
||||||
|
Assert.check(rc == Sjavac.RC_OK, "Compilation failed unexpectedly.");
|
||||||
|
|
||||||
|
// The resulting .class files should correspond to the visible source files
|
||||||
|
Set<Path> result = allFilesInDir(BIN);
|
||||||
|
Set<Path> expected = correspondingClassFiles(sourcesExpectedToBeVisible);
|
||||||
|
if (!result.equals(expected)) {
|
||||||
|
System.out.println("Result:");
|
||||||
|
printPaths(result);
|
||||||
|
System.out.println("Expected:");
|
||||||
|
printPaths(expected);
|
||||||
|
Assert.error("Test case failed: " + filterArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printPaths(Collection<Path> paths) {
|
||||||
|
paths.stream()
|
||||||
|
.sorted()
|
||||||
|
.forEachOrdered(p -> System.out.println(" " + p));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given "pkg/A.java, pkg/B.java" this method returns "bin/pkg/A.class, bin/pkg/B.class"
|
||||||
|
Set<Path> correspondingClassFiles(Collection<Path> javaFiles) {
|
||||||
|
return javaFiles.stream()
|
||||||
|
.map(javaFile -> javaFile.resolveSibling(classNameOf(javaFile) + ".class"))
|
||||||
|
.map(BIN::resolve)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Path> allFilesInDir(Path p) throws IOException {
|
||||||
|
try (Stream<Path> files = Files.walk(p).filter(Files::isRegularFile)) {
|
||||||
|
return files.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,7 +61,6 @@ public class OptionDecoding {
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
testPaths();
|
testPaths();
|
||||||
testDupPaths();
|
testDupPaths();
|
||||||
testSourceLocations();
|
|
||||||
testSimpleOptions();
|
testSimpleOptions();
|
||||||
testServerConf();
|
testServerConf();
|
||||||
testSearchPaths();
|
testSearchPaths();
|
||||||
|
@ -110,78 +109,6 @@ public class OptionDecoding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test source locations and -x, -i, -xf, -if filters
|
|
||||||
static void testSourceLocations() throws IOException {
|
|
||||||
Path a1 = Paths.get("root/pkg1/ClassA1.java");
|
|
||||||
Path a2 = Paths.get("root/pkg1/ClassA2.java");
|
|
||||||
Path b1 = Paths.get("root/pkg1/pkg2/ClassB1.java");
|
|
||||||
Path b2 = Paths.get("root/pkg1/pkg2/ClassB2.java");
|
|
||||||
Path c1 = Paths.get("root/pkg3/ClassC1.java");
|
|
||||||
Path c2 = Paths.get("root/pkg3/ClassC2.java");
|
|
||||||
|
|
||||||
for (Path p : Arrays.asList(a1, a2, b1, b2, c1, c2)) {
|
|
||||||
Files.createDirectories(p.getParent());
|
|
||||||
Files.createFile(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test -if
|
|
||||||
{
|
|
||||||
Options options = Options.parseArgs("-if", "root/pkg1/ClassA1.java", "root");
|
|
||||||
|
|
||||||
Map<String, Source> foundFiles = new HashMap<>();
|
|
||||||
SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
|
|
||||||
new HashMap<String, Module>(), new Module("", ""), false, true);
|
|
||||||
|
|
||||||
checkFilesFound(foundFiles.keySet(), a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test -i
|
|
||||||
System.out.println("--------------------------- CHECKING -i ----------------");
|
|
||||||
{
|
|
||||||
Options options = Options.parseArgs("-i", "pkg1/*", "root");
|
|
||||||
|
|
||||||
Map<String, Source> foundFiles = new HashMap<>();
|
|
||||||
SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
|
|
||||||
new HashMap<String, Module>(), new Module("", ""), false, true);
|
|
||||||
|
|
||||||
checkFilesFound(foundFiles.keySet(), a1, a2, b1, b2);
|
|
||||||
}
|
|
||||||
System.out.println("--------------------------------------------------------");
|
|
||||||
|
|
||||||
// Test -xf
|
|
||||||
{
|
|
||||||
Options options = Options.parseArgs("-xf", "root/pkg1/ClassA1.java", "root");
|
|
||||||
|
|
||||||
Map<String, Source> foundFiles = new HashMap<>();
|
|
||||||
SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
|
|
||||||
new HashMap<String, Module>(), new Module("", ""), false, true);
|
|
||||||
|
|
||||||
checkFilesFound(foundFiles.keySet(), a2, b1, b2, c1, c2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test -x
|
|
||||||
{
|
|
||||||
Options options = Options.parseArgs("-i", "pkg1/*", "root");
|
|
||||||
|
|
||||||
Map<String, Source> foundFiles = new HashMap<>();
|
|
||||||
SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
|
|
||||||
new HashMap<String, Module>(), new Module("", ""), false, true);
|
|
||||||
|
|
||||||
checkFilesFound(foundFiles.keySet(), a1, a2, b1, b2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test -x and -i
|
|
||||||
{
|
|
||||||
Options options = Options.parseArgs("-i", "pkg1/*", "-x", "pkg1/pkg2/*", "root");
|
|
||||||
|
|
||||||
Map<String, Source> foundFiles = new HashMap<>();
|
|
||||||
SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
|
|
||||||
new HashMap<String, Module>(), new Module("", ""), false, true);
|
|
||||||
|
|
||||||
checkFilesFound(foundFiles.keySet(), a1, a2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test basic options
|
// Test basic options
|
||||||
static void testSimpleOptions() {
|
static void testSimpleOptions() {
|
||||||
Options options = Options.parseArgs("-j", "17", "--log=debug");
|
Options options = Options.parseArgs("-j", "17", "--log=debug");
|
||||||
|
@ -216,8 +143,8 @@ public class OptionDecoding {
|
||||||
List<String> i, x, iF, xF;
|
List<String> i, x, iF, xF;
|
||||||
i = x = iF = xF = new ArrayList<>();
|
i = x = iF = xF = new ArrayList<>();
|
||||||
|
|
||||||
SourceLocation dir1 = new SourceLocation(Paths.get("dir1"), i, x, iF, xF);
|
SourceLocation dir1 = new SourceLocation(Paths.get("dir1"), i, x);
|
||||||
SourceLocation dir2 = new SourceLocation(Paths.get("dir2"), i, x, iF, xF);
|
SourceLocation dir2 = new SourceLocation(Paths.get("dir2"), i, x);
|
||||||
String dir1_PS_dir2 = "dir1" + File.pathSeparator + "dir2";
|
String dir1_PS_dir2 = "dir1" + File.pathSeparator + "dir2";
|
||||||
|
|
||||||
Options options = Options.parseArgs("-sourcepath", dir1_PS_dir2);
|
Options options = Options.parseArgs("-sourcepath", dir1_PS_dir2);
|
||||||
|
|
|
@ -58,8 +58,6 @@ public class Serialization {
|
||||||
Option.D.arg, "dest",
|
Option.D.arg, "dest",
|
||||||
Option.I.arg, "pkg/*",
|
Option.I.arg, "pkg/*",
|
||||||
Option.X.arg, "pkg/pkg/*",
|
Option.X.arg, "pkg/pkg/*",
|
||||||
Option.IF.arg, "root/pkg/MyClass1.java",
|
|
||||||
Option.XF.arg, "root/pkg/MyClass2.java",
|
|
||||||
Option.SRC.arg, "root",
|
Option.SRC.arg, "root",
|
||||||
Option.SOURCEPATH.arg, "sourcepath",
|
Option.SOURCEPATH.arg, "sourcepath",
|
||||||
Option.CLASSPATH.arg, "classpath",
|
Option.CLASSPATH.arg, "classpath",
|
||||||
|
@ -87,8 +85,6 @@ public class Serialization {
|
||||||
assertEquals(sl1.getPath(), sl2.getPath());
|
assertEquals(sl1.getPath(), sl2.getPath());
|
||||||
assertEquals(sl1.getIncludes(), sl2.getIncludes());
|
assertEquals(sl1.getIncludes(), sl2.getIncludes());
|
||||||
assertEquals(sl1.getExcludes(), sl2.getExcludes());
|
assertEquals(sl1.getExcludes(), sl2.getExcludes());
|
||||||
assertEquals(sl1.getIncludedFiles(), sl2.getIncludedFiles());
|
|
||||||
assertEquals(sl1.getExcludedFiles(), sl2.getExcludedFiles());
|
|
||||||
|
|
||||||
assertEquals(options1.getClassSearchPath(), options2.getClassSearchPath());
|
assertEquals(options1.getClassSearchPath(), options2.getClassSearchPath());
|
||||||
assertEquals(options1.getSourceSearchPaths(), options2.getSourceSearchPaths());
|
assertEquals(options1.getSourceSearchPaths(), options2.getSourceSearchPaths());
|
||||||
|
|
|
@ -62,9 +62,7 @@ public class OptionTestUtil {
|
||||||
|
|
||||||
if (!sl1.getPath().equals(sl2.getPath()) ||
|
if (!sl1.getPath().equals(sl2.getPath()) ||
|
||||||
!sl1.getIncludes().equals(sl2.getIncludes()) ||
|
!sl1.getIncludes().equals(sl2.getIncludes()) ||
|
||||||
!sl1.getExcludes().equals(sl2.getExcludes()) ||
|
!sl1.getExcludes().equals(sl2.getExcludes()))
|
||||||
!sl1.getIncludedFiles().equals(sl2.getIncludedFiles()) ||
|
|
||||||
!sl1.getExcludedFiles().equals(sl2.getExcludedFiles()))
|
|
||||||
throw new AssertionError("Expected " + sl1 + " but got " + sl2);
|
throw new AssertionError("Expected " + sl1 + " but got " + sl2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue