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;
20
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Set;
24 import java.util.regex.Pattern;
25
26 import org.apache.maven.api.services.BuilderProblem;
27 import org.apache.maven.api.settings.Mirror;
28 import org.apache.maven.api.settings.Profile;
29 import org.apache.maven.api.settings.Proxy;
30 import org.apache.maven.api.settings.Repository;
31 import org.apache.maven.api.settings.Server;
32 import org.apache.maven.api.settings.Settings;
33
34
35
36 public class DefaultSettingsValidator {
37
38 private static final String ID = "[\\w.-]+";
39 private static final Pattern ID_REGEX = Pattern.compile(ID);
40
41 private static final String ILLEGAL_REPO_ID_CHARS = "\\/:\"<>|?*";
42
43 public void validate(Settings settings, boolean isProjectSettings, List<BuilderProblem> problems) {
44 if (isProjectSettings) {
45 String msgS = "is not supported on project settings.";
46 String msgP = "are not supported on project settings.";
47 if (settings.getLocalRepository() != null
48 && !settings.getLocalRepository().isEmpty()) {
49 addViolation(problems, BuilderProblem.Severity.WARNING, "localRepository", null, msgS);
50 }
51 if (!settings.isInteractiveMode()) {
52 addViolation(problems, BuilderProblem.Severity.WARNING, "interactiveMode", null, msgS);
53 }
54 if (settings.isOffline()) {
55 addViolation(problems, BuilderProblem.Severity.WARNING, "offline", null, msgS);
56 }
57 if (!settings.getProxies().isEmpty()) {
58 addViolation(problems, BuilderProblem.Severity.WARNING, "proxies", null, msgP);
59 }
60 if (settings.isUsePluginRegistry()) {
61 addViolation(problems, BuilderProblem.Severity.WARNING, "usePluginRegistry", null, msgS);
62 }
63 List<Server> servers = settings.getServers();
64 for (int i = 0; i < servers.size(); i++) {
65 Server server = servers.get(i);
66 String serverField = "servers.server[" + i + "]";
67 validateStringEmpty(problems, serverField + ".username", server.getUsername(), msgS);
68 validateStringEmpty(problems, serverField + ".password", server.getPassword(), msgS);
69 validateStringEmpty(problems, serverField + ".privateKey", server.getPrivateKey(), msgS);
70 validateStringEmpty(problems, serverField + ".passphrase", server.getPassphrase(), msgS);
71 validateStringEmpty(problems, serverField + ".filePermissions", server.getFilePermissions(), msgS);
72 validateStringEmpty(
73 problems, serverField + ".directoryPermissions", server.getDirectoryPermissions(), msgS);
74 }
75 }
76
77 if (settings.isUsePluginRegistry()) {
78 addViolation(
79 problems,
80 BuilderProblem.Severity.WARNING,
81 "usePluginRegistry",
82 null,
83 "is deprecated and has no effect.");
84 }
85
86 List<String> pluginGroups = settings.getPluginGroups();
87
88 if (pluginGroups != null) {
89 for (int i = 0; i < pluginGroups.size(); i++) {
90 String pluginGroup = pluginGroups.get(i);
91
92 validateStringNotEmpty(problems, "pluginGroups.pluginGroup[" + i + "]", pluginGroup, null);
93
94 if (!ID_REGEX.matcher(pluginGroup).matches()) {
95 addViolation(
96 problems,
97 BuilderProblem.Severity.ERROR,
98 "pluginGroups.pluginGroup[" + i + "]",
99 null,
100 "must denote a valid group id and match the pattern " + ID);
101 }
102 }
103 }
104
105 List<Server> servers = settings.getServers();
106
107 if (servers != null) {
108 Set<String> serverIds = new HashSet<>();
109
110 for (int i = 0; i < servers.size(); i++) {
111 Server server = servers.get(i);
112
113 validateStringNotEmpty(problems, "servers.server[" + i + "].id", server.getId(), null);
114
115 if (!serverIds.add(server.getId())) {
116 addViolation(
117 problems,
118 BuilderProblem.Severity.WARNING,
119 "servers.server.id",
120 null,
121 "must be unique but found duplicate server with id " + server.getId());
122 }
123 }
124 }
125
126 List<Mirror> mirrors = settings.getMirrors();
127
128 if (mirrors != null) {
129 for (Mirror mirror : mirrors) {
130 validateStringNotEmpty(problems, "mirrors.mirror.id", mirror.getId(), mirror.getUrl());
131
132 validateBannedCharacters(
133 problems,
134 "mirrors.mirror.id",
135 BuilderProblem.Severity.WARNING,
136 mirror.getId(),
137 null,
138 ILLEGAL_REPO_ID_CHARS);
139
140 if ("local".equals(mirror.getId())) {
141 addViolation(
142 problems,
143 BuilderProblem.Severity.WARNING,
144 "mirrors.mirror.id",
145 null,
146 "must not be 'local'"
147 + ", this identifier is reserved for the local repository"
148 + ", using it for other repositories will corrupt your repository metadata.");
149 }
150
151 validateStringNotEmpty(problems, "mirrors.mirror.url", mirror.getUrl(), mirror.getId());
152
153 validateStringNotEmpty(problems, "mirrors.mirror.mirrorOf", mirror.getMirrorOf(), mirror.getId());
154 }
155 }
156
157 List<Profile> profiles = settings.getProfiles();
158
159 if (profiles != null) {
160 Set<String> profileIds = new HashSet<>();
161
162 for (Profile profile : profiles) {
163 if (!profileIds.add(profile.getId())) {
164 addViolation(
165 problems,
166 BuilderProblem.Severity.WARNING,
167 "profiles.profile.id",
168 null,
169 "must be unique but found duplicate profile with id " + profile.getId());
170 }
171
172 String prefix = "profiles.profile[" + profile.getId() + "].";
173
174 validateRepositories(problems, profile.getRepositories(), prefix + "repositories.repository");
175 validateRepositories(
176 problems, profile.getPluginRepositories(), prefix + "pluginRepositories.pluginRepository");
177 }
178 }
179
180 List<Proxy> proxies = settings.getProxies();
181
182 if (proxies != null) {
183 Set<String> proxyIds = new HashSet<>();
184
185 for (Proxy proxy : proxies) {
186 if (!proxyIds.add(proxy.getId())) {
187 addViolation(
188 problems,
189 BuilderProblem.Severity.WARNING,
190 "proxies.proxy.id",
191 null,
192 "must be unique but found duplicate proxy with id " + proxy.getId());
193 }
194 validateStringNotEmpty(problems, "proxies.proxy.host", proxy.getHost(), proxy.getId());
195
196 try {
197 Integer.parseInt(proxy.getPortString());
198 } catch (NumberFormatException e) {
199 addViolation(
200 problems,
201 BuilderProblem.Severity.ERROR,
202 "proxies.proxy[" + proxy.getId() + "].port",
203 null,
204 "must be a valid integer but found '" + proxy.getPortString() + "'");
205 }
206 }
207 }
208 }
209
210 private void validateRepositories(List<BuilderProblem> problems, List<Repository> repositories, String prefix) {
211 Set<String> repoIds = new HashSet<>();
212
213 for (Repository repository : repositories) {
214 validateStringNotEmpty(problems, prefix + ".id", repository.getId(), repository.getUrl());
215
216 validateBannedCharacters(
217 problems,
218 prefix + ".id",
219 BuilderProblem.Severity.WARNING,
220 repository.getId(),
221 null,
222 ILLEGAL_REPO_ID_CHARS);
223
224 if ("local".equals(repository.getId())) {
225 addViolation(
226 problems,
227 BuilderProblem.Severity.WARNING,
228 prefix + ".id",
229 null,
230 "must not be 'local'"
231 + ", this identifier is reserved for the local repository"
232 + ", using it for other repositories will corrupt your repository metadata.");
233 }
234
235 if (!repoIds.add(repository.getId())) {
236 addViolation(
237 problems,
238 BuilderProblem.Severity.WARNING,
239 prefix + ".id",
240 null,
241 "must be unique but found duplicate repository with id " + repository.getId());
242 }
243
244 validateStringNotEmpty(problems, prefix + ".url", repository.getUrl(), repository.getId());
245
246 if ("legacy".equals(repository.getLayout())) {
247 addViolation(
248 problems,
249 BuilderProblem.Severity.WARNING,
250 prefix + ".layout",
251 repository.getId(),
252 "uses the unsupported value 'legacy', artifact resolution might fail.");
253 }
254 }
255 }
256
257
258
259
260
261
262
263
264
265
266
267
268
269 private static boolean validateStringEmpty(
270 List<BuilderProblem> problems, String fieldName, String string, String message) {
271 if (string == null || string.length() == 0) {
272 return true;
273 }
274
275 addViolation(problems, BuilderProblem.Severity.WARNING, fieldName, null, message);
276
277 return false;
278 }
279
280
281
282
283
284
285
286
287
288 private static boolean validateStringNotEmpty(
289 List<BuilderProblem> problems, String fieldName, String string, String sourceHint) {
290 if (!validateNotNull(problems, fieldName, string, sourceHint)) {
291 return false;
292 }
293
294 if (!string.isEmpty()) {
295 return true;
296 }
297
298 addViolation(problems, BuilderProblem.Severity.ERROR, fieldName, sourceHint, "is missing");
299
300 return false;
301 }
302
303
304
305
306
307
308
309
310 private static boolean validateNotNull(
311 List<BuilderProblem> problems, String fieldName, Object object, String sourceHint) {
312 if (object != null) {
313 return true;
314 }
315
316 addViolation(problems, BuilderProblem.Severity.ERROR, fieldName, sourceHint, "is missing");
317
318 return false;
319 }
320
321 private static boolean validateBannedCharacters(
322 List<BuilderProblem> problems,
323 String fieldName,
324 BuilderProblem.Severity severity,
325 String string,
326 String sourceHint,
327 String banned) {
328 if (string != null) {
329 for (int i = string.length() - 1; i >= 0; i--) {
330 if (banned.indexOf(string.charAt(i)) >= 0) {
331 addViolation(
332 problems,
333 severity,
334 fieldName,
335 sourceHint,
336 "must not contain any of these characters " + banned + " but found " + string.charAt(i));
337 return false;
338 }
339 }
340 }
341
342 return true;
343 }
344
345 private static void addViolation(
346 List<BuilderProblem> problems,
347 BuilderProblem.Severity severity,
348 String fieldName,
349 String sourceHint,
350 String message) {
351 StringBuilder buffer = new StringBuilder(256);
352 buffer.append('\'').append(fieldName).append('\'');
353
354 if (sourceHint != null) {
355 buffer.append(" for ").append(sourceHint);
356 }
357
358 buffer.append(' ').append(message);
359
360 problems.add(new DefaultBuilderProblem(null, -1, -1, null, buffer.toString(), severity));
361 }
362 }