1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package jdk.tools.jlink.internal.plugins;
26
27import java.io.File;
28import java.io.IOException;
29import java.io.UncheckedIOException;
30import java.nio.file.Files;
31import java.nio.file.Path;
32import java.nio.file.PathMatcher;
33import java.util.ArrayList;
34import java.util.Collections;
35import java.util.List;
36import java.util.Objects;
37import java.util.function.Predicate;
38import jdk.tools.jlink.internal.Utils;
39
40/**
41 *
42 * Filter resource resources using path matcher.
43 */
44public class ResourceFilter implements Predicate<String> {
45    private final static List<String> EMPTY_LIST = Collections.emptyList();
46
47    private final List<PathMatcher> matchers;
48    private final boolean include;
49    private final boolean otherwise;
50
51    private ResourceFilter(List<String> patterns, boolean exclude) {
52        Objects.requireNonNull(patterns);
53        this.matchers = new ArrayList<>();
54
55        for (String pattern : patterns) {
56            if (pattern.startsWith("@")) {
57                File file = new File(pattern.substring(1));
58
59                if (file.exists()) {
60                    List<String> lines;
61
62                    try {
63                        lines = Files.readAllLines(file.toPath());
64                    } catch (IOException ex) {
65                        throw new UncheckedIOException(ex);
66                    }
67
68                    lines.stream().forEach((line) -> {
69                        matchers.add(Utils.getJRTFSPathMatcher(line.trim()));
70                    });
71                } else {
72                    System.err.println("warning - the filter file " + file +
73                                       " is empty or not present.");
74                }
75            } else {
76                matchers.add(Utils.getJRTFSPathMatcher(pattern));
77            }
78        }
79
80        this.include = !exclude;
81        this.otherwise = exclude || this.matchers.isEmpty();
82    }
83
84    public static ResourceFilter includeFilter(List<String> patterns) {
85        Objects.requireNonNull(patterns);
86        return new ResourceFilter(patterns, false);
87    }
88
89    public static ResourceFilter includeFilter(String patterns) {
90        if (patterns == null) {
91            return includeFilter(EMPTY_LIST);
92        }
93
94        return includeFilter(Utils.parseList(patterns));
95    }
96
97    public static ResourceFilter excludeFilter(List<String> patterns) {
98        Objects.requireNonNull(patterns);
99        return new ResourceFilter(patterns, true);
100    }
101
102    public static ResourceFilter excludeFilter(String patterns) {
103        if (patterns == null) {
104            return excludeFilter(EMPTY_LIST);
105        }
106
107        return excludeFilter(Utils.parseList(patterns));
108    }
109
110    @Override
111    public boolean test(String name) {
112        Objects.requireNonNull(name);
113        Path path = Utils.getJRTFSPath(name);
114
115        for (PathMatcher matcher : matchers) {
116            if (matcher.matches(path)) {
117                return include;
118            }
119        }
120
121        return otherwise;
122    }
123}
124