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