mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-12 08:53:12 +00:00
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
Reviewed-by: sundar, alanb
This commit is contained in:
parent
32757e8ed8
commit
50e2a2ced0
@ -28,7 +28,9 @@ package jdk.tools.jimage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -43,9 +45,10 @@ import jdk.tools.jlink.internal.TaskHelper.BadArgs;
|
||||
import static jdk.tools.jlink.internal.TaskHelper.JIMAGE_BUNDLE;
|
||||
import jdk.tools.jlink.internal.TaskHelper.Option;
|
||||
import jdk.tools.jlink.internal.TaskHelper.OptionsHelper;
|
||||
import jdk.tools.jlink.internal.Utils;
|
||||
|
||||
class JImageTask {
|
||||
static final Option<?>[] recognizedOptions = {
|
||||
private static final Option<?>[] RECOGNIZED_OPTIONS = {
|
||||
new Option<JImageTask>(true, (task, option, arg) -> {
|
||||
task.options.directory = arg;
|
||||
}, "--dir"),
|
||||
@ -70,15 +73,16 @@ class JImageTask {
|
||||
task.options.version = true;
|
||||
}, "--version")
|
||||
};
|
||||
private static final TaskHelper taskHelper
|
||||
private static final TaskHelper TASK_HELPER
|
||||
= new TaskHelper(JIMAGE_BUNDLE);
|
||||
private static final OptionsHelper<JImageTask> optionsHelper
|
||||
= taskHelper.newOptionsHelper(JImageTask.class, recognizedOptions);
|
||||
private static final OptionsHelper<JImageTask> OPTION_HELPER
|
||||
= TASK_HELPER.newOptionsHelper(JImageTask.class, RECOGNIZED_OPTIONS);
|
||||
private static final String PROGNAME = "jimage";
|
||||
private static final FileSystem JRT_FILE_SYSTEM = Utils.jrtFileSystem();
|
||||
|
||||
private final OptionsValues options;
|
||||
private final List<Predicate<String>> filterPredicates;
|
||||
private PrintWriter log = null;
|
||||
private PrintWriter log;
|
||||
|
||||
JImageTask() {
|
||||
this.options = new OptionsValues();
|
||||
@ -88,7 +92,7 @@ class JImageTask {
|
||||
|
||||
void setLog(PrintWriter out) {
|
||||
log = out;
|
||||
taskHelper.setLog(log);
|
||||
TASK_HELPER.setLog(log);
|
||||
}
|
||||
|
||||
static class OptionsValues {
|
||||
@ -160,32 +164,32 @@ class JImageTask {
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
log.println(taskHelper.getMessage("main.usage.summary", PROGNAME));
|
||||
log.println(TASK_HELPER.getMessage("main.usage.summary", PROGNAME));
|
||||
return EXIT_ABNORMAL;
|
||||
}
|
||||
|
||||
try {
|
||||
List<String> unhandled = optionsHelper.handleOptions(this, args);
|
||||
List<String> unhandled = OPTION_HELPER.handleOptions(this, args);
|
||||
|
||||
if(!unhandled.isEmpty()) {
|
||||
try {
|
||||
options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw taskHelper.newBadArgs("err.not.a.task", unhandled.get(0));
|
||||
throw TASK_HELPER.newBadArgs("err.not.a.task", unhandled.get(0));
|
||||
}
|
||||
|
||||
for(int i = 1; i < unhandled.size(); i++) {
|
||||
options.jimages.add(new File(unhandled.get(i)));
|
||||
}
|
||||
} else if (!options.help && !options.version && !options.fullVersion) {
|
||||
throw taskHelper.newBadArgs("err.invalid.task", "<unspecified>");
|
||||
throw TASK_HELPER.newBadArgs("err.invalid.task", "<unspecified>");
|
||||
}
|
||||
|
||||
if (options.help) {
|
||||
if (unhandled.isEmpty()) {
|
||||
log.println(taskHelper.getMessage("main.usage", PROGNAME));
|
||||
log.println(TASK_HELPER.getMessage("main.usage", PROGNAME));
|
||||
|
||||
for (Option<?> o : recognizedOptions) {
|
||||
for (Option<?> o : RECOGNIZED_OPTIONS) {
|
||||
String name = o.aliases()[0];
|
||||
|
||||
if (name.startsWith("--")) {
|
||||
@ -194,21 +198,21 @@ class JImageTask {
|
||||
name = name.substring(1);
|
||||
}
|
||||
|
||||
log.println(taskHelper.getMessage("main.opt." + name));
|
||||
log.println(TASK_HELPER.getMessage("main.opt." + name));
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
log.println(taskHelper.getMessage("main.usage." +
|
||||
log.println(TASK_HELPER.getMessage("main.usage." +
|
||||
options.task.toString().toLowerCase()));
|
||||
} catch (MissingResourceException ex) {
|
||||
throw taskHelper.newBadArgs("err.not.a.task", unhandled.get(0));
|
||||
throw TASK_HELPER.newBadArgs("err.not.a.task", unhandled.get(0));
|
||||
}
|
||||
}
|
||||
return EXIT_OK;
|
||||
}
|
||||
|
||||
if (options.version || options.fullVersion) {
|
||||
taskHelper.showVersion(options.fullVersion);
|
||||
TASK_HELPER.showVersion(options.fullVersion);
|
||||
|
||||
if (unhandled.isEmpty()) {
|
||||
return EXIT_OK;
|
||||
@ -219,10 +223,10 @@ class JImageTask {
|
||||
|
||||
return run() ? EXIT_OK : EXIT_ERROR;
|
||||
} catch (BadArgs e) {
|
||||
taskHelper.reportError(e.key, e.args);
|
||||
TASK_HELPER.reportError(e.key, e.args);
|
||||
|
||||
if (e.showUsage) {
|
||||
log.println(taskHelper.getMessage("main.usage.summary", PROGNAME));
|
||||
log.println(TASK_HELPER.getMessage("main.usage.summary", PROGNAME));
|
||||
}
|
||||
|
||||
return EXIT_CMDERR;
|
||||
@ -241,25 +245,9 @@ class JImageTask {
|
||||
}
|
||||
|
||||
for (String filter : filters.split(",")) {
|
||||
boolean endsWith = filter.startsWith("*");
|
||||
boolean startsWith = filter.endsWith("*");
|
||||
Predicate<String> function;
|
||||
|
||||
if (startsWith && endsWith) {
|
||||
final String string = filter.substring(1, filter.length() - 1);
|
||||
function = (path) -> path.contains(string);
|
||||
} else if (startsWith) {
|
||||
final String string = filter.substring(0, filter.length() - 1);
|
||||
function = (path) -> path.startsWith(string);
|
||||
} else if (endsWith) {
|
||||
final String string = filter.substring(1);
|
||||
function = (path) -> path.endsWith(string);
|
||||
} else {
|
||||
final String string = filter;
|
||||
function = (path) -> path.equals(string);
|
||||
}
|
||||
|
||||
filterPredicates.add(function);
|
||||
final PathMatcher matcher = Utils.getPathMatcher(JRT_FILE_SYSTEM, filter);
|
||||
Predicate<String> predicate = (path) -> matcher.matches(JRT_FILE_SYSTEM.getPath(path));
|
||||
filterPredicates.add(predicate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,11 +278,11 @@ class JImageTask {
|
||||
|
||||
if (parent.exists()) {
|
||||
if (!parent.isDirectory()) {
|
||||
throw taskHelper.newBadArgs("err.cannot.create.dir",
|
||||
throw TASK_HELPER.newBadArgs("err.cannot.create.dir",
|
||||
parent.getAbsolutePath());
|
||||
}
|
||||
} else if (!parent.mkdirs()) {
|
||||
throw taskHelper.newBadArgs("err.cannot.create.dir",
|
||||
throw TASK_HELPER.newBadArgs("err.cannot.create.dir",
|
||||
parent.getAbsolutePath());
|
||||
}
|
||||
|
||||
@ -382,12 +370,12 @@ class JImageTask {
|
||||
ModuleAction moduleAction,
|
||||
ResourceAction resourceAction) throws IOException, BadArgs {
|
||||
if (options.jimages.isEmpty()) {
|
||||
throw taskHelper.newBadArgs("err.no.jimage");
|
||||
throw TASK_HELPER.newBadArgs("err.no.jimage");
|
||||
}
|
||||
|
||||
for (File file : options.jimages) {
|
||||
if (!file.exists() || !file.isFile()) {
|
||||
throw taskHelper.newBadArgs("err.not.a.jimage", file.getName());
|
||||
throw TASK_HELPER.newBadArgs("err.not.a.jimage", file.getName());
|
||||
}
|
||||
|
||||
try (BasicImageReader reader = BasicImageReader.open(file.toPath())) {
|
||||
@ -451,7 +439,7 @@ class JImageTask {
|
||||
iterate(this::listTitle, null, this::verify);
|
||||
break;
|
||||
default:
|
||||
throw taskHelper.newBadArgs("err.invalid.task",
|
||||
throw TASK_HELPER.newBadArgs("err.invalid.task",
|
||||
options.task.name()).showUsage(true);
|
||||
}
|
||||
return true;
|
||||
|
||||
@ -25,6 +25,10 @@
|
||||
package jdk.tools.jlink.internal;
|
||||
|
||||
import java.lang.reflect.Module;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
@ -155,4 +159,20 @@ public class Utils {
|
||||
public static boolean isBuiltin(Plugin prov) {
|
||||
return THIS_MODULE.equals(prov.getClass().getModule());
|
||||
}
|
||||
|
||||
public static FileSystem jrtFileSystem() {
|
||||
return FileSystems.getFileSystem(URI.create("jrt:/"));
|
||||
}
|
||||
|
||||
public static PathMatcher getPathMatcher(FileSystem fs, String pattern) {
|
||||
if (!pattern.startsWith("glob:") && !pattern.startsWith("regex:")) {
|
||||
pattern = "glob:" + pattern;
|
||||
}
|
||||
|
||||
return fs.getPathMatcher(pattern);
|
||||
}
|
||||
|
||||
public static PathMatcher getPathMatcher(String pattern) {
|
||||
return getPathMatcher(jrtFileSystem(), pattern);
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,9 @@ package jdk.tools.jlink.internal.plugins;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -47,6 +49,8 @@ import jdk.tools.jlink.internal.Utils;
|
||||
*/
|
||||
public final class OrderResourcesPlugin implements TransformerPlugin {
|
||||
public static final String NAME = "order-resources";
|
||||
private static final FileSystem JRT_FILE_SYSTEM = Utils.jrtFileSystem();
|
||||
|
||||
private final List<ToIntFunction<String>> filters;
|
||||
private final Map<String, Integer> orderedPaths;
|
||||
|
||||
@ -187,27 +191,11 @@ public final class OrderResourcesPlugin implements TransformerPlugin {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
boolean endsWith = pattern.startsWith("*");
|
||||
boolean startsWith = pattern.endsWith("*");
|
||||
ToIntFunction<String> function;
|
||||
final int result = ordinal++;
|
||||
|
||||
if (startsWith && endsWith) {
|
||||
final String string = pattern.substring(1, pattern.length() - 1);
|
||||
function = (path)-> path.contains(string) ? result : Integer.MAX_VALUE;
|
||||
} else if (startsWith) {
|
||||
final String string = pattern.substring(0, pattern.length() - 1);
|
||||
function = (path)-> path.startsWith(string) ? result : Integer.MAX_VALUE;
|
||||
} else if (endsWith) {
|
||||
final String string = pattern.substring(1);
|
||||
function = (path)-> path.endsWith(string) ? result : Integer.MAX_VALUE;
|
||||
} else {
|
||||
final String string = pattern;
|
||||
function = (path)-> path.equals(string) ? result : Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
final PathMatcher matcher = Utils.getPathMatcher(JRT_FILE_SYSTEM, pattern);
|
||||
ToIntFunction<String> function = (path)-> matcher.matches(JRT_FILE_SYSTEM.getPath(path)) ? result : Integer.MAX_VALUE;
|
||||
filters.add(function);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,113 +24,71 @@
|
||||
*/
|
||||
package jdk.tools.jlink.internal.plugins;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import jdk.tools.jlink.internal.Utils;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Filter in or out a resource
|
||||
* Filter resource resources using path matcher.
|
||||
*/
|
||||
public class ResourceFilter implements Predicate<String> {
|
||||
private static final FileSystem JRT_FILE_SYSTEM = Utils.jrtFileSystem();
|
||||
|
||||
private final Pattern inPatterns;
|
||||
private final Pattern outPatterns;
|
||||
|
||||
static final String NEG = "^";
|
||||
final boolean negate;
|
||||
final List<PathMatcher> matchers;
|
||||
|
||||
public ResourceFilter(String[] patterns) throws IOException {
|
||||
this(patterns, false);
|
||||
}
|
||||
|
||||
public ResourceFilter(String[] patterns, boolean negateAll) throws IOException {
|
||||
public ResourceFilter(String[] patterns, boolean negate) throws IOException {
|
||||
this.negate = negate;
|
||||
this.matchers = new ArrayList<>();
|
||||
|
||||
// Get the patterns from a file
|
||||
if (patterns != null && patterns.length == 1) {
|
||||
String filePath = patterns[0];
|
||||
File f = new File(filePath);
|
||||
if (f.exists()) {
|
||||
List<String> pats;
|
||||
try (FileInputStream fis = new FileInputStream(f);
|
||||
InputStreamReader ins = new InputStreamReader(fis,
|
||||
StandardCharsets.UTF_8);
|
||||
BufferedReader reader = new BufferedReader(ins)) {
|
||||
pats = reader.lines().collect(Collectors.toList());
|
||||
for (String pattern : patterns) {
|
||||
if (pattern.startsWith("@")) {
|
||||
File file = new File(pattern.substring(1));
|
||||
|
||||
if (file.exists()) {
|
||||
List<String> lines;
|
||||
|
||||
try {
|
||||
lines = Files.readAllLines(file.toPath());
|
||||
} catch (IOException ex) {
|
||||
throw new PluginException(ex);
|
||||
}
|
||||
|
||||
for (String line : lines) {
|
||||
PathMatcher matcher = Utils.getPathMatcher(JRT_FILE_SYSTEM, line);
|
||||
matchers.add(matcher);
|
||||
}
|
||||
}
|
||||
patterns = new String[pats.size()];
|
||||
pats.toArray(patterns);
|
||||
} else {
|
||||
PathMatcher matcher = Utils.getPathMatcher(JRT_FILE_SYSTEM, pattern);
|
||||
matchers.add(matcher);
|
||||
}
|
||||
}
|
||||
|
||||
if (patterns != null && negateAll) {
|
||||
String[] excluded = new String[patterns.length];
|
||||
for (int i = 0; i < patterns.length; i++) {
|
||||
excluded[i] = ResourceFilter.NEG + patterns[i];
|
||||
}
|
||||
patterns = excluded;
|
||||
}
|
||||
|
||||
StringBuilder inPatternsBuilder = new StringBuilder();
|
||||
StringBuilder outPatternsBuilder = new StringBuilder();
|
||||
if (patterns != null) {
|
||||
for (int i = 0; i < patterns.length; i++) {
|
||||
String p = patterns[i];
|
||||
p = p.replaceAll(" ", "");
|
||||
StringBuilder builder = p.startsWith(NEG)
|
||||
? outPatternsBuilder : inPatternsBuilder;
|
||||
String pat = p.startsWith(NEG) ? p.substring(NEG.length()) : p;
|
||||
builder.append(escape(pat));
|
||||
if (i < patterns.length - 1) {
|
||||
builder.append("|");
|
||||
}
|
||||
}
|
||||
}
|
||||
this.inPatterns = inPatternsBuilder.length() == 0 ? null
|
||||
: Pattern.compile(inPatternsBuilder.toString());
|
||||
this.outPatterns = outPatternsBuilder.length() == 0 ? null
|
||||
: Pattern.compile(outPatternsBuilder.toString());
|
||||
}
|
||||
|
||||
public static String escape(String s) {
|
||||
s = s.replaceAll(" ", "");
|
||||
s = s.replaceAll("\\$", Matcher.quoteReplacement("\\$"));
|
||||
s = s.replaceAll("\\.", Matcher.quoteReplacement("\\."));
|
||||
s = s.replaceAll("\\*", ".+");
|
||||
return s;
|
||||
}
|
||||
|
||||
private boolean accept(String path) {
|
||||
if (outPatterns != null) {
|
||||
Matcher mout = outPatterns.matcher(path);
|
||||
if (mout.matches()) {
|
||||
//System.out.println("Excluding file " + resource.getPath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
boolean accepted = false;
|
||||
// If the inPatterns is null, means that all resources are accepted.
|
||||
if (inPatterns == null) {
|
||||
accepted = true;
|
||||
} else {
|
||||
Matcher m = inPatterns.matcher(path);
|
||||
if (m.matches()) {
|
||||
//System.out.println("Including file " + resource.getPath());
|
||||
accepted = true;
|
||||
}
|
||||
}
|
||||
return accepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(String path) {
|
||||
return accept(path);
|
||||
public boolean test(String name) {
|
||||
Path path = JRT_FILE_SYSTEM.getPath(name);
|
||||
|
||||
for (PathMatcher matcher : matchers) {
|
||||
if (matcher.matches(path)) {
|
||||
return !negate;
|
||||
}
|
||||
}
|
||||
|
||||
return negate;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1072,6 +1072,10 @@ public class JmodTask {
|
||||
@Override
|
||||
public Pattern convert(String value) {
|
||||
try {
|
||||
if (value.startsWith("regex:")) {
|
||||
value = value.substring("regex:".length()).trim();
|
||||
}
|
||||
|
||||
return Pattern.compile(value);
|
||||
} catch (PatternSyntaxException e) {
|
||||
throw new CommandException("err.bad.pattern", value);
|
||||
@ -1083,10 +1087,15 @@ public class JmodTask {
|
||||
@Override public String valuePattern() { return "pattern"; }
|
||||
}
|
||||
|
||||
static class GlobConverter implements ValueConverter<PathMatcher> {
|
||||
static class PathMatcherConverter implements ValueConverter<PathMatcher> {
|
||||
@Override
|
||||
public PathMatcher convert(String pattern) {
|
||||
try {
|
||||
if (!pattern.startsWith("glob:") &&
|
||||
!pattern.startsWith("regex:")) {
|
||||
pattern = "glob:" + pattern;
|
||||
}
|
||||
|
||||
return FileSystems.getDefault()
|
||||
.getPathMatcher("glob:" + pattern);
|
||||
} catch (PatternSyntaxException e) {
|
||||
@ -1194,7 +1203,7 @@ public class JmodTask {
|
||||
OptionSpec<PathMatcher> excludes
|
||||
= parser.accepts("exclude", getMessage("main.opt.exclude"))
|
||||
.withRequiredArg()
|
||||
.withValuesConvertedBy(new GlobConverter());
|
||||
.withValuesConvertedBy(new PathMatcherConverter());
|
||||
|
||||
OptionSpec<Pattern> hashModules
|
||||
= parser.accepts("hash-modules", getMessage("main.opt.hash-modules"))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user