1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.buildcache.checksum.exclude;
20
21 import java.nio.file.Files;
22 import java.nio.file.Path;
23 import java.nio.file.Paths;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Properties;
30 import java.util.Set;
31
32 import org.apache.maven.buildcache.xml.CacheConfig;
33 import org.apache.maven.buildcache.xml.config.Exclude;
34 import org.apache.maven.model.Build;
35 import org.apache.maven.project.MavenProject;
36
37 public class ExclusionResolver {
38
39
40
41
42
43 private static final String PROJECT_PROPERTY_EXCLUDE_PREFIX = "maven.build.cache.exclude";
44
45 public static final String PROJECT_PROPERTY_EXCLUDE_VALUE = PROJECT_PROPERTY_EXCLUDE_PREFIX + ".value";
46 public static final String PROJECT_PROPERTY_EXCLUDE_GLOB = PROJECT_PROPERTY_EXCLUDE_PREFIX + ".glob";
47 public static final String PROJECT_PROPERTY_EXCLUDE_ENTRY_TYPE = PROJECT_PROPERTY_EXCLUDE_PREFIX + ".entryType";
48 public static final String PROJECT_PROPERTY_EXCLUDE_MATCHER_TYPE = PROJECT_PROPERTY_EXCLUDE_PREFIX + ".matcherType";
49
50
51
52
53 private final List<Exclusion> directoryExclusions = new ArrayList<>();
54
55
56
57 private final List<Exclusion> filesExclusions = new ArrayList<>();
58
59
60
61 private final Set<Path> directFileExclusions = new HashSet<>();
62
63 private final Path projectBaseDirectory;
64
65 public ExclusionResolver(MavenProject project, CacheConfig config) {
66 addDefaultExcludes(project);
67 Path baseDirectory = project.getBasedir().toPath().toAbsolutePath();
68 projectBaseDirectory = baseDirectory;
69
70
71 List<Exclude> excludes = config.getGlobalExcludePaths();
72 for (Exclude exclude : excludes) {
73 addExclusion(baseDirectory, exclude);
74 }
75
76
77 Properties properties = project.getProperties();
78 Map<String, Exclude> propertyMap = new HashMap<>();
79 for (String propertyName : properties.stringPropertyNames()) {
80 if (propertyName.startsWith(PROJECT_PROPERTY_EXCLUDE_VALUE)) {
81 String propertyKey = propertyName.substring(PROJECT_PROPERTY_EXCLUDE_VALUE.length());
82 Exclude exclude = propertyMap.computeIfAbsent(propertyKey, key -> new Exclude());
83 exclude.setValue(properties.getProperty(propertyName));
84 } else if (propertyName.startsWith(PROJECT_PROPERTY_EXCLUDE_GLOB)) {
85 String propertyKey = propertyName.substring(PROJECT_PROPERTY_EXCLUDE_GLOB.length());
86 Exclude exclude = propertyMap.computeIfAbsent(propertyKey, key -> new Exclude());
87 exclude.setGlob(properties.getProperty(propertyName));
88 } else if (propertyName.startsWith(PROJECT_PROPERTY_EXCLUDE_ENTRY_TYPE)) {
89 String propertyKey = propertyName.substring(PROJECT_PROPERTY_EXCLUDE_ENTRY_TYPE.length());
90 Exclude exclude = propertyMap.computeIfAbsent(propertyKey, key -> new Exclude());
91 exclude.setEntryType(properties.getProperty(propertyName));
92 } else if (propertyName.startsWith(PROJECT_PROPERTY_EXCLUDE_MATCHER_TYPE)) {
93 String propertyKey = propertyName.substring(PROJECT_PROPERTY_EXCLUDE_MATCHER_TYPE.length());
94 Exclude exclude = propertyMap.computeIfAbsent(propertyKey, key -> new Exclude());
95 exclude.setMatcherType(properties.getProperty(propertyName));
96 }
97 }
98 for (Exclude propertyExclude : propertyMap.values()) {
99 addExclusion(baseDirectory, propertyExclude);
100 }
101 }
102
103 private void addExclusion(Path baseDirectory, Exclude exclude) {
104 Exclusion exclusion = new Exclusion(baseDirectory, exclude);
105
106 if (!Files.exists(exclusion.getAbsolutePath())) {
107
108
109 return;
110 }
111
112 if (Files.isDirectory(exclusion.getAbsolutePath())) {
113 switch (exclusion.getEntryType()) {
114 case ALL:
115 directoryExclusions.add(exclusion);
116 filesExclusions.add(exclusion);
117 break;
118 case FILE:
119 filesExclusions.add(exclusion);
120 break;
121 case DIRECTORY:
122 directoryExclusions.add(exclusion);
123 break;
124 default:
125 throw new RuntimeException("Exclusion range not handled.");
126 }
127 } else {
128 directFileExclusions.add(exclusion.getAbsolutePath());
129 }
130 }
131
132 private void addDefaultExcludes(MavenProject project) {
133 Build build = project.getBuild();
134
135 Path buildDirectoryPath = absoluteNormalizedPath(build.getDirectory());
136
137 Path outputDirectoryPath = absoluteNormalizedPath(build.getOutputDirectory());
138
139 Path testOutputDirectoryPath = absoluteNormalizedPath(build.getTestOutputDirectory());
140
141 addFileAndDirectoryExclusion(
142 new Exclusion(buildDirectoryPath, Exclusion.MatcherType.FILENAME, Exclusion.EntryType.ALL));
143
144 if (!outputDirectoryPath.startsWith(buildDirectoryPath)) {
145 addFileAndDirectoryExclusion(
146 new Exclusion(outputDirectoryPath, Exclusion.MatcherType.FILENAME, Exclusion.EntryType.ALL));
147 }
148 if (!testOutputDirectoryPath.startsWith(buildDirectoryPath)) {
149 addFileAndDirectoryExclusion(
150 new Exclusion(testOutputDirectoryPath, Exclusion.MatcherType.FILENAME, Exclusion.EntryType.ALL));
151 }
152 }
153
154 private void addFileAndDirectoryExclusion(final Exclusion exclusion) {
155 directoryExclusions.add(exclusion);
156 filesExclusions.add(exclusion);
157 }
158
159 private Path absoluteNormalizedPath(String directory) {
160 return Paths.get(directory).toAbsolutePath().normalize();
161 }
162
163 public boolean excludesPath(Path entryAbsolutePath) {
164 boolean isDirectory = Files.isDirectory(entryAbsolutePath);
165
166 if (!isDirectory && directFileExclusions.contains(entryAbsolutePath)) {
167 return true;
168 }
169 List<Exclusion> exclusionList = isDirectory ? directoryExclusions : filesExclusions;
170 for (Exclusion exclusion : exclusionList) {
171 if (exclusion.excludesPath(projectBaseDirectory, entryAbsolutePath)) {
172 return true;
173 }
174 }
175 return false;
176 }
177 }