1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.impl.model.profile;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.nio.file.FileVisitResult;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.nio.file.PathMatcher;
27 import java.nio.file.Paths;
28 import java.nio.file.SimpleFileVisitor;
29 import java.nio.file.attribute.BasicFileAttributes;
30 import java.util.List;
31 import java.util.concurrent.atomic.AtomicBoolean;
32
33 import org.apache.maven.api.services.VersionParser;
34 import org.apache.maven.api.services.model.ProfileActivationContext;
35 import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
36
37 import static org.apache.maven.internal.impl.model.profile.ConditionParser.toInt;
38
39
40
41
42
43
44 @SuppressWarnings("unused")
45 public class ConditionFunctions {
46 private final ProfileActivationContext context;
47 private final VersionParser versionParser;
48 private final ProfileActivationFilePathInterpolator interpolator;
49
50
51
52
53
54
55
56
57 public ConditionFunctions(
58 ProfileActivationContext context,
59 VersionParser versionParser,
60 ProfileActivationFilePathInterpolator interpolator) {
61 this.context = context;
62 this.versionParser = versionParser;
63 this.interpolator = interpolator;
64 }
65
66
67
68
69
70
71
72
73 public Object length(List<Object> args) {
74 if (args.size() != 1) {
75 throw new IllegalArgumentException("length function requires exactly one argument");
76 }
77 String s = ConditionParser.toString(args.get(0));
78 return s.length();
79 }
80
81
82
83
84
85
86
87
88 public Object upper(List<Object> args) {
89 if (args.size() != 1) {
90 throw new IllegalArgumentException("upper function requires exactly one argument");
91 }
92 String s = ConditionParser.toString(args.get(0));
93 return s.toUpperCase();
94 }
95
96
97
98
99
100
101
102
103 public Object lower(List<Object> args) {
104 if (args.size() != 1) {
105 throw new IllegalArgumentException("lower function requires exactly one argument");
106 }
107 String s = ConditionParser.toString(args.get(0));
108 return s.toLowerCase();
109 }
110
111
112
113
114
115
116
117
118 public Object substring(List<Object> args) {
119 if (args.size() < 2 || args.size() > 3) {
120 throw new IllegalArgumentException("substring function requires 2 or 3 arguments");
121 }
122 String s = ConditionParser.toString(args.get(0));
123 int start = toInt(args.get(1));
124 int end = args.size() == 3 ? toInt(args.get(2)) : s.length();
125 return s.substring(start, end);
126 }
127
128
129
130
131
132
133
134
135 public Object indexOf(List<Object> args) {
136 if (args.size() != 2) {
137 throw new IllegalArgumentException("indexOf function requires exactly two arguments");
138 }
139 String s = ConditionParser.toString(args.get(0));
140 String substring = ConditionParser.toString(args.get(1));
141 return s.indexOf(substring);
142 }
143
144
145
146
147
148
149
150
151 public Object contains(List<Object> args) {
152 if (args.size() != 2) {
153 throw new IllegalArgumentException("contains function requires exactly two arguments");
154 }
155 String s = ConditionParser.toString(args.get(0));
156 String substring = ConditionParser.toString(args.get(1));
157 return s.contains(substring);
158 }
159
160
161
162
163
164
165
166
167 public Object matches(List<Object> args) {
168 if (args.size() != 2) {
169 throw new IllegalArgumentException("matches function requires exactly two arguments");
170 }
171 String s = ConditionParser.toString(args.get(0));
172 String regex = ConditionParser.toString(args.get(1));
173 return s.matches(regex);
174 }
175
176
177
178
179
180
181
182
183 public Object not(List<Object> args) {
184 if (args.size() != 1) {
185 throw new IllegalArgumentException("not function requires exactly one argument");
186 }
187 return !ConditionParser.toBoolean(args.get(0));
188 }
189
190
191
192
193
194
195
196
197 @SuppressWarnings("checkstyle:MethodName")
198 public Object if_(List<Object> args) {
199 if (args.size() != 3) {
200 throw new IllegalArgumentException("if function requires exactly three arguments");
201 }
202 boolean condition = ConditionParser.toBoolean(args.get(0));
203 return condition ? args.get(1) : args.get(2);
204 }
205
206
207
208
209
210
211
212
213
214 public Object exists(List<Object> args) throws IOException {
215 if (args.size() != 1) {
216 throw new IllegalArgumentException("exists function requires exactly one argument");
217 }
218 String path = ConditionParser.toString(args.get(0));
219 return fileExists(path);
220 }
221
222
223
224
225
226
227
228
229
230 public Object missing(List<Object> args) throws IOException {
231 if (args.size() != 1) {
232 throw new IllegalArgumentException("missing function requires exactly one argument");
233 }
234 String path = ConditionParser.toString(args.get(0));
235 return !fileExists(path);
236 }
237
238 private boolean fileExists(String path) throws IOException {
239 String pattern = interpolator.interpolate(path, context);
240 int asteriskIndex = pattern.indexOf('*');
241 int questionMarkIndex = pattern.indexOf('?');
242 int firstWildcardIndex = questionMarkIndex < 0
243 ? asteriskIndex
244 : asteriskIndex < 0 ? questionMarkIndex : Math.min(asteriskIndex, questionMarkIndex);
245 String fixed, glob;
246 if (firstWildcardIndex < 0) {
247 fixed = pattern;
248 glob = "";
249 } else {
250 int lastSep = pattern.substring(0, firstWildcardIndex).lastIndexOf(File.separatorChar);
251 if (lastSep < 0) {
252 fixed = "";
253 glob = pattern;
254 } else {
255 fixed = pattern.substring(0, lastSep);
256 glob = pattern.substring(lastSep + 1);
257 }
258 }
259 Path fixedPath = Paths.get(fixed);
260 if (!Files.exists(fixedPath)) {
261 return false;
262 }
263 if (!glob.isEmpty()) {
264 PathMatcher matcher = fixedPath.getFileSystem().getPathMatcher("glob:" + glob);
265 AtomicBoolean found = new AtomicBoolean(false);
266 Files.walkFileTree(fixedPath, new SimpleFileVisitor<>() {
267 @Override
268 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
269 if (found.get() || matcher.matches(fixedPath.relativize(file))) {
270 found.set(true);
271 return FileVisitResult.TERMINATE;
272 }
273 return FileVisitResult.CONTINUE;
274 }
275 });
276 return found.get();
277 }
278 return true;
279 }
280
281
282
283
284
285
286
287
288 public Object inrange(List<Object> args) {
289 if (args.size() != 2) {
290 throw new IllegalArgumentException("inrange function requires exactly two arguments");
291 }
292 String version = ConditionParser.toString(args.get(0));
293 String range = ConditionParser.toString(args.get(1));
294 return versionParser.parseVersionRange(range).contains(versionParser.parseVersion(version));
295 }
296 }