1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.model.validation;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.io.File;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Objects;
32 import java.util.Set;
33 import java.util.regex.Matcher;
34 import java.util.regex.Pattern;
35
36 import org.apache.maven.model.Activation;
37 import org.apache.maven.model.ActivationFile;
38 import org.apache.maven.model.Build;
39 import org.apache.maven.model.BuildBase;
40 import org.apache.maven.model.Dependency;
41 import org.apache.maven.model.DependencyManagement;
42 import org.apache.maven.model.DistributionManagement;
43 import org.apache.maven.model.Exclusion;
44 import org.apache.maven.model.InputLocation;
45 import org.apache.maven.model.InputLocationTracker;
46 import org.apache.maven.model.Model;
47 import org.apache.maven.model.Parent;
48 import org.apache.maven.model.Plugin;
49 import org.apache.maven.model.PluginExecution;
50 import org.apache.maven.model.PluginManagement;
51 import org.apache.maven.model.Profile;
52 import org.apache.maven.model.ReportPlugin;
53 import org.apache.maven.model.Reporting;
54 import org.apache.maven.model.Repository;
55 import org.apache.maven.model.Resource;
56 import org.apache.maven.model.building.ModelBuildingRequest;
57 import org.apache.maven.model.building.ModelProblem.Severity;
58 import org.apache.maven.model.building.ModelProblem.Version;
59 import org.apache.maven.model.building.ModelProblemCollector;
60 import org.apache.maven.model.building.ModelProblemCollectorRequest;
61 import org.apache.maven.model.interpolation.ModelVersionProcessor;
62 import org.codehaus.plexus.util.StringUtils;
63
64
65
66
67 @Named
68 @Singleton
69 public class DefaultModelValidator implements ModelValidator {
70
71 private static final Pattern CI_FRIENDLY_EXPRESSION = Pattern.compile("\\$\\{(.+?)}");
72
73 private static final String ILLEGAL_FS_CHARS = "\\/:\"<>|?*";
74
75 private static final String ILLEGAL_VERSION_CHARS = ILLEGAL_FS_CHARS;
76
77 private static final String ILLEGAL_REPO_ID_CHARS = ILLEGAL_FS_CHARS;
78
79 private static final String EMPTY = "";
80
81 private final Set<String> validIds = new HashSet<>();
82
83 private ModelVersionProcessor versionProcessor;
84
85 @Inject
86 public DefaultModelValidator(ModelVersionProcessor versionProcessor) {
87 this.versionProcessor = versionProcessor;
88 }
89
90 @Override
91 public void validateRawModel(Model m, ModelBuildingRequest request, ModelProblemCollector problems) {
92 Parent parent = m.getParent();
93 if (parent != null) {
94 validateStringNotEmpty(
95 "parent.groupId", problems, Severity.FATAL, Version.BASE, parent.getGroupId(), parent);
96
97 validateStringNotEmpty(
98 "parent.artifactId", problems, Severity.FATAL, Version.BASE, parent.getArtifactId(), parent);
99
100 validateStringNotEmpty(
101 "parent.version", problems, Severity.FATAL, Version.BASE, parent.getVersion(), parent);
102
103 if (equals(parent.getGroupId(), m.getGroupId()) && equals(parent.getArtifactId(), m.getArtifactId())) {
104 addViolation(
105 problems,
106 Severity.FATAL,
107 Version.BASE,
108 "parent.artifactId",
109 null,
110 "must be changed"
111 + ", the parent element cannot have the same groupId:artifactId as the project.",
112 parent);
113 }
114
115 if (equals("LATEST", parent.getVersion()) || equals("RELEASE", parent.getVersion())) {
116 addViolation(
117 problems,
118 Severity.WARNING,
119 Version.BASE,
120 "parent.version",
121 null,
122 "is either LATEST or RELEASE (both of them are being deprecated)",
123 parent);
124 }
125 }
126
127 if (request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
128 Severity errOn30 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0);
129
130
131
132
133
134
135
136 validateStringNotEmpty("modelVersion", problems, Severity.ERROR, Version.V20, m.getModelVersion(), m);
137
138 validateModelVersion(problems, m.getModelVersion(), m, "4.0.0");
139
140 validateStringNoExpression("groupId", problems, Severity.WARNING, Version.V20, m.getGroupId(), m);
141 if (parent == null) {
142 validateStringNotEmpty("groupId", problems, Severity.FATAL, Version.V20, m.getGroupId(), m);
143 }
144
145 validateStringNoExpression("artifactId", problems, Severity.WARNING, Version.V20, m.getArtifactId(), m);
146 validateStringNotEmpty("artifactId", problems, Severity.FATAL, Version.V20, m.getArtifactId(), m);
147
148 validateVersionNoExpression("version", problems, Severity.WARNING, Version.V20, m.getVersion(), m);
149 if (parent == null) {
150 validateStringNotEmpty("version", problems, Severity.FATAL, Version.V20, m.getVersion(), m);
151 }
152
153 validate20RawDependencies(problems, m.getDependencies(), "dependencies.dependency.", EMPTY, request);
154
155 validate20RawDependenciesSelfReferencing(
156 problems, m, m.getDependencies(), "dependencies.dependency", request);
157
158 if (m.getDependencyManagement() != null) {
159 validate20RawDependencies(
160 problems,
161 m.getDependencyManagement().getDependencies(),
162 "dependencyManagement.dependencies.dependency.",
163 EMPTY,
164 request);
165 }
166
167 validateRawRepositories(problems, m.getRepositories(), "repositories.repository.", EMPTY, request);
168
169 validateRawRepositories(
170 problems, m.getPluginRepositories(), "pluginRepositories.pluginRepository.", EMPTY, request);
171
172 Build build = m.getBuild();
173 if (build != null) {
174 validate20RawPlugins(problems, build.getPlugins(), "build.plugins.plugin.", EMPTY, request);
175
176 PluginManagement mgmt = build.getPluginManagement();
177 if (mgmt != null) {
178 validate20RawPlugins(
179 problems, mgmt.getPlugins(), "build.pluginManagement.plugins.plugin.", EMPTY, request);
180 }
181 }
182
183 Set<String> profileIds = new HashSet<>();
184
185 for (Profile profile : m.getProfiles()) {
186 String prefix = "profiles.profile[" + profile.getId() + "].";
187
188 if (!profileIds.add(profile.getId())) {
189 addViolation(
190 problems,
191 errOn30,
192 Version.V20,
193 "profiles.profile.id",
194 null,
195 "must be unique but found duplicate profile with id " + profile.getId(),
196 profile);
197 }
198
199 validate30RawProfileActivation(
200 problems, profile.getActivation(), profile.getId(), prefix, "activation", request);
201
202 validate20RawDependencies(
203 problems, profile.getDependencies(), prefix, "dependencies.dependency.", request);
204
205 if (profile.getDependencyManagement() != null) {
206 validate20RawDependencies(
207 problems,
208 profile.getDependencyManagement().getDependencies(),
209 prefix,
210 "dependencyManagement.dependencies.dependency.",
211 request);
212 }
213
214 validateRawRepositories(
215 problems, profile.getRepositories(), prefix, "repositories.repository.", request);
216
217 validateRawRepositories(
218 problems,
219 profile.getPluginRepositories(),
220 prefix,
221 "pluginRepositories.pluginRepository.",
222 request);
223
224 BuildBase buildBase = profile.getBuild();
225 if (buildBase != null) {
226 validate20RawPlugins(problems, buildBase.getPlugins(), prefix, "plugins.plugin.", request);
227
228 PluginManagement mgmt = buildBase.getPluginManagement();
229 if (mgmt != null) {
230 validate20RawPlugins(
231 problems, mgmt.getPlugins(), prefix, "pluginManagement.plugins.plugin.", request);
232 }
233 }
234 }
235 }
236 }
237
238 private void validate30RawProfileActivation(
239 ModelProblemCollector problems,
240 Activation activation,
241 String sourceHint,
242 String prefix,
243 String fieldName,
244 ModelBuildingRequest request) {
245 if (activation == null) {
246 return;
247 }
248
249 ActivationFile file = activation.getFile();
250
251 if (file != null) {
252 String path;
253 boolean missing;
254
255 if (StringUtils.isNotEmpty(file.getExists())) {
256 path = file.getExists();
257 missing = false;
258 } else if (StringUtils.isNotEmpty(file.getMissing())) {
259 path = file.getMissing();
260 missing = true;
261 } else {
262 return;
263 }
264
265 if (path.contains("${project.basedir}")) {
266 addViolation(
267 problems,
268 Severity.WARNING,
269 Version.V30,
270 prefix + fieldName + (missing ? ".file.missing" : ".file.exists"),
271 null,
272 "Failed to interpolate file location " + path + " for profile " + sourceHint
273 + ": ${project.basedir} expression not supported during profile activation, "
274 + "use ${basedir} instead",
275 file.getLocation(missing ? "missing" : "exists"));
276 } else if (hasProjectExpression(path)) {
277 addViolation(
278 problems,
279 Severity.WARNING,
280 Version.V30,
281 prefix + fieldName + (missing ? ".file.missing" : ".file.exists"),
282 null,
283 "Failed to interpolate file location " + path + " for profile " + sourceHint
284 + ": ${project.*} expressions are not supported during profile activation",
285 file.getLocation(missing ? "missing" : "exists"));
286 }
287 }
288 }
289
290 private void validate20RawPlugins(
291 ModelProblemCollector problems,
292 List<Plugin> plugins,
293 String prefix,
294 String prefix2,
295 ModelBuildingRequest request) {
296 Severity errOn31 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_1);
297
298 Map<String, Plugin> index = new HashMap<>();
299
300 for (Plugin plugin : plugins) {
301 if (plugin.getGroupId() == null
302 || (plugin.getGroupId() != null
303 && plugin.getGroupId().trim().isEmpty())) {
304 addViolation(
305 problems,
306 Severity.FATAL,
307 Version.V20,
308 prefix + prefix2 + "(groupId:artifactId)",
309 null,
310 "groupId of a plugin must be defined. ",
311 plugin);
312 }
313
314 if (plugin.getArtifactId() == null
315 || (plugin.getArtifactId() != null
316 && plugin.getArtifactId().trim().isEmpty())) {
317 addViolation(
318 problems,
319 Severity.FATAL,
320 Version.V20,
321 prefix + prefix2 + "(groupId:artifactId)",
322 null,
323 "artifactId of a plugin must be defined. ",
324 plugin);
325 }
326
327
328 if (plugin.getVersion() != null && plugin.getVersion().trim().isEmpty()) {
329 addViolation(
330 problems,
331 Severity.FATAL,
332 Version.V20,
333 prefix + prefix2 + "(groupId:artifactId)",
334 null,
335 "version of a plugin must be defined. ",
336 plugin);
337 }
338
339 String key = plugin.getKey();
340
341 Plugin existing = index.get(key);
342
343 if (existing != null) {
344 addViolation(
345 problems,
346 errOn31,
347 Version.V20,
348 prefix + prefix2 + "(groupId:artifactId)",
349 null,
350 "must be unique but found duplicate declaration of plugin " + key,
351 plugin);
352 } else {
353 index.put(key, plugin);
354 }
355
356 Set<String> executionIds = new HashSet<>();
357
358 for (PluginExecution exec : plugin.getExecutions()) {
359 if (!executionIds.add(exec.getId())) {
360 addViolation(
361 problems,
362 Severity.ERROR,
363 Version.V20,
364 prefix + prefix2 + "[" + plugin.getKey() + "].executions.execution.id",
365 null,
366 "must be unique but found duplicate execution with id " + exec.getId(),
367 exec);
368 }
369 }
370 }
371 }
372
373 @Override
374 @SuppressWarnings("checkstyle:MethodLength")
375 public void validateEffectiveModel(Model m, ModelBuildingRequest request, ModelProblemCollector problems) {
376 validateStringNotEmpty("modelVersion", problems, Severity.ERROR, Version.BASE, m.getModelVersion(), m);
377
378 validateId("groupId", problems, m.getGroupId(), m);
379
380 validateId("artifactId", problems, m.getArtifactId(), m);
381
382 validateStringNotEmpty("packaging", problems, Severity.ERROR, Version.BASE, m.getPackaging(), m);
383
384 if (!m.getModules().isEmpty()) {
385 if (!"pom".equals(m.getPackaging())) {
386 addViolation(
387 problems,
388 Severity.ERROR,
389 Version.BASE,
390 "packaging",
391 null,
392 "with value '" + m.getPackaging() + "' is invalid. Aggregator projects "
393 + "require 'pom' as packaging.",
394 m);
395 }
396
397 for (int i = 0, n = m.getModules().size(); i < n; i++) {
398 String module = m.getModules().get(i);
399 if (StringUtils.isBlank(module)) {
400 addViolation(
401 problems,
402 Severity.ERROR,
403 Version.BASE,
404 "modules.module[" + i + "]",
405 null,
406 "has been specified without a path to the project directory.",
407 m.getLocation("modules"));
408 }
409 }
410 }
411
412 validateStringNotEmpty("version", problems, Severity.ERROR, Version.BASE, m.getVersion(), m);
413
414 Severity errOn30 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0);
415
416 validateEffectiveDependencies(problems, m, m.getDependencies(), false, request);
417
418 DependencyManagement mgmt = m.getDependencyManagement();
419 if (mgmt != null) {
420 validateEffectiveDependencies(problems, m, mgmt.getDependencies(), true, request);
421 }
422
423 if (request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
424 Set<String> modules = new HashSet<>();
425 for (int i = 0, n = m.getModules().size(); i < n; i++) {
426 String module = m.getModules().get(i);
427 if (!modules.add(module)) {
428 addViolation(
429 problems,
430 Severity.ERROR,
431 Version.V20,
432 "modules.module[" + i + "]",
433 null,
434 "specifies duplicate child module " + module,
435 m.getLocation("modules"));
436 }
437 }
438
439 Severity errOn31 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_1);
440
441 validateBannedCharacters(
442 EMPTY, "version", problems, errOn31, Version.V20, m.getVersion(), null, m, ILLEGAL_VERSION_CHARS);
443 validate20ProperSnapshotVersion("version", problems, errOn31, Version.V20, m.getVersion(), null, m);
444
445 Build build = m.getBuild();
446 if (build != null) {
447 for (Plugin p : build.getPlugins()) {
448 validateStringNotEmpty(
449 "build.plugins.plugin.artifactId",
450 problems,
451 Severity.ERROR,
452 Version.V20,
453 p.getArtifactId(),
454 p);
455
456 validateStringNotEmpty(
457 "build.plugins.plugin.groupId", problems, Severity.ERROR, Version.V20, p.getGroupId(), p);
458
459 validate20PluginVersion(
460 "build.plugins.plugin.version", problems, p.getVersion(), p.getKey(), p, request);
461
462 validateBoolean(
463 "build.plugins.plugin.inherited",
464 EMPTY,
465 problems,
466 errOn30,
467 Version.V20,
468 p.getInherited(),
469 p.getKey(),
470 p);
471
472 validateBoolean(
473 "build.plugins.plugin.extensions",
474 EMPTY,
475 problems,
476 errOn30,
477 Version.V20,
478 p.getExtensions(),
479 p.getKey(),
480 p);
481
482 validate20EffectivePluginDependencies(problems, p, request);
483 }
484
485 validate20RawResources(problems, build.getResources(), "build.resources.resource.", request);
486
487 validate20RawResources(
488 problems, build.getTestResources(), "build.testResources.testResource.", request);
489 }
490
491 Reporting reporting = m.getReporting();
492 if (reporting != null) {
493 for (ReportPlugin p : reporting.getPlugins()) {
494 validateStringNotEmpty(
495 "reporting.plugins.plugin.artifactId",
496 problems,
497 Severity.ERROR,
498 Version.V20,
499 p.getArtifactId(),
500 p);
501
502 validateStringNotEmpty(
503 "reporting.plugins.plugin.groupId",
504 problems,
505 Severity.ERROR,
506 Version.V20,
507 p.getGroupId(),
508 p);
509 }
510 }
511
512 for (Repository repository : m.getRepositories()) {
513 validate20EffectiveRepository(problems, repository, "repositories.repository.", request);
514 }
515
516 for (Repository repository : m.getPluginRepositories()) {
517 validate20EffectiveRepository(problems, repository, "pluginRepositories.pluginRepository.", request);
518 }
519
520 DistributionManagement distMgmt = m.getDistributionManagement();
521 if (distMgmt != null) {
522 if (distMgmt.getStatus() != null) {
523 addViolation(
524 problems,
525 Severity.ERROR,
526 Version.V20,
527 "distributionManagement.status",
528 null,
529 "must not be specified.",
530 distMgmt);
531 }
532
533 validate20EffectiveRepository(
534 problems, distMgmt.getRepository(), "distributionManagement.repository.", request);
535 validate20EffectiveRepository(
536 problems,
537 distMgmt.getSnapshotRepository(),
538 "distributionManagement.snapshotRepository.",
539 request);
540 }
541 }
542 }
543
544 private void validate20RawDependencies(
545 ModelProblemCollector problems,
546 List<Dependency> dependencies,
547 String prefix,
548 String prefix2,
549 ModelBuildingRequest request) {
550 Severity errOn30 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0);
551 Severity errOn31 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_1);
552
553 Map<String, Dependency> index = new HashMap<>();
554
555 for (Dependency dependency : dependencies) {
556 String key = dependency.getManagementKey();
557
558 if ("import".equals(dependency.getScope())) {
559 if (!"pom".equals(dependency.getType())) {
560 addViolation(
561 problems,
562 Severity.WARNING,
563 Version.V20,
564 prefix + prefix2 + "type",
565 key,
566 "must be 'pom' to import the managed dependencies.",
567 dependency);
568 } else if (StringUtils.isNotEmpty(dependency.getClassifier())) {
569 addViolation(
570 problems,
571 errOn30,
572 Version.V20,
573 prefix + prefix2 + "classifier",
574 key,
575 "must be empty, imported POM cannot have a classifier.",
576 dependency);
577 }
578 } else if ("system".equals(dependency.getScope())) {
579
580 if (request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_1) {
581 addViolation(
582 problems,
583 Severity.WARNING,
584 Version.V31,
585 prefix + prefix2 + "scope",
586 key,
587 "declares usage of deprecated 'system' scope ",
588 dependency);
589 }
590
591 String sysPath = dependency.getSystemPath();
592 if (StringUtils.isNotEmpty(sysPath)) {
593 if (!hasExpression(sysPath)) {
594 addViolation(
595 problems,
596 Severity.WARNING,
597 Version.V20,
598 prefix + prefix2 + "systemPath",
599 key,
600 "should use a variable instead of a hard-coded path " + sysPath,
601 dependency);
602 } else if (sysPath.contains("${basedir}") || sysPath.contains("${project.basedir}")) {
603 addViolation(
604 problems,
605 Severity.WARNING,
606 Version.V20,
607 prefix + prefix2 + "systemPath",
608 key,
609 "should not point at files within the project directory, " + sysPath
610 + " will be unresolvable by dependent projects",
611 dependency);
612 }
613 }
614 }
615
616 if (equals("LATEST", dependency.getVersion()) || equals("RELEASE", dependency.getVersion())) {
617 addViolation(
618 problems,
619 Severity.WARNING,
620 Version.BASE,
621 prefix + prefix2 + "version",
622 key,
623 "is either LATEST or RELEASE (both of them are being deprecated)",
624 dependency);
625 }
626
627 Dependency existing = index.get(key);
628
629 if (existing != null) {
630 String msg;
631 if (equals(existing.getVersion(), dependency.getVersion())) {
632 msg = "duplicate declaration of version " + Objects.toString(dependency.getVersion(), "(?)");
633 } else {
634 msg = "version " + Objects.toString(existing.getVersion(), "(?)") + " vs "
635 + Objects.toString(dependency.getVersion(), "(?)");
636 }
637
638 addViolation(
639 problems,
640 errOn31,
641 Version.V20,
642 prefix + prefix2 + "(groupId:artifactId:type:classifier)",
643 null,
644 "must be unique: " + key + " -> " + msg,
645 dependency);
646 } else {
647 index.put(key, dependency);
648 }
649 }
650 }
651
652 private void validate20RawDependenciesSelfReferencing(
653 ModelProblemCollector problems,
654 Model m,
655 List<Dependency> dependencies,
656 String prefix,
657 ModelBuildingRequest request) {
658
659
660
661
662
663 for (Dependency dependency : dependencies) {
664 String key = dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getVersion()
665 + (dependency.getClassifier() != null ? ":" + dependency.getClassifier() : EMPTY);
666 String mKey = m.getGroupId() + ":" + m.getArtifactId() + ":" + m.getVersion();
667 if (key.equals(mKey)) {
668
669
670
671 addViolation(
672 problems,
673 Severity.FATAL,
674 Version.V31,
675 prefix + "[" + key + "]",
676 key,
677 "is referencing itself.",
678 dependency);
679 }
680 }
681 }
682
683 private void validateEffectiveDependencies(
684 ModelProblemCollector problems,
685 Model m,
686 List<Dependency> dependencies,
687 boolean management,
688 ModelBuildingRequest request) {
689 Severity errOn30 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0);
690
691 String prefix = management ? "dependencyManagement.dependencies.dependency." : "dependencies.dependency.";
692
693 for (Dependency d : dependencies) {
694 validateEffectiveDependency(problems, d, management, prefix, request);
695
696 if (request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
697 validateBoolean(
698 prefix, "optional", problems, errOn30, Version.V20, d.getOptional(), d.getManagementKey(), d);
699
700 if (!management) {
701 validateVersion(
702 prefix, "version", problems, errOn30, Version.V20, d.getVersion(), d.getManagementKey(), d);
703
704
705
706
707
708 validateEnum(
709 prefix,
710 "scope",
711 problems,
712 Severity.WARNING,
713 Version.V20,
714 d.getScope(),
715 d.getManagementKey(),
716 d,
717 "provided",
718 "compile",
719 "runtime",
720 "test",
721 "system");
722
723 validateEffectiveModelAgainstDependency(prefix, problems, m, d, request);
724 } else {
725 validateEnum(
726 prefix,
727 "scope",
728 problems,
729 Severity.WARNING,
730 Version.V20,
731 d.getScope(),
732 d.getManagementKey(),
733 d,
734 "provided",
735 "compile",
736 "runtime",
737 "test",
738 "system",
739 "import");
740 }
741 }
742 }
743 }
744
745 private void validateEffectiveModelAgainstDependency(
746 String prefix, ModelProblemCollector problems, Model m, Dependency d, ModelBuildingRequest request) {
747 String key = d.getGroupId() + ":" + d.getArtifactId() + ":" + d.getVersion()
748 + (d.getClassifier() != null ? ":" + d.getClassifier() : EMPTY);
749 String mKey = m.getGroupId() + ":" + m.getArtifactId() + ":" + m.getVersion();
750 if (key.equals(mKey)) {
751
752
753
754 addViolation(
755 problems, Severity.FATAL, Version.V31, prefix + "[" + key + "]", key, "is referencing itself.", d);
756 }
757 }
758
759 private void validate20EffectivePluginDependencies(
760 ModelProblemCollector problems, Plugin plugin, ModelBuildingRequest request) {
761 List<Dependency> dependencies = plugin.getDependencies();
762
763 if (!dependencies.isEmpty()) {
764 String prefix = "build.plugins.plugin[" + plugin.getKey() + "].dependencies.dependency.";
765
766 Severity errOn30 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0);
767
768 for (Dependency d : dependencies) {
769 validateEffectiveDependency(problems, d, false, prefix, request);
770
771 validateVersion(
772 prefix, "version", problems, errOn30, Version.BASE, d.getVersion(), d.getManagementKey(), d);
773
774 validateEnum(
775 prefix,
776 "scope",
777 problems,
778 errOn30,
779 Version.BASE,
780 d.getScope(),
781 d.getManagementKey(),
782 d,
783 "compile",
784 "runtime",
785 "system");
786 }
787 }
788 }
789
790 private void validateEffectiveDependency(
791 ModelProblemCollector problems,
792 Dependency d,
793 boolean management,
794 String prefix,
795 ModelBuildingRequest request) {
796 validateId(
797 prefix,
798 "artifactId",
799 problems,
800 Severity.ERROR,
801 Version.BASE,
802 d.getArtifactId(),
803 d.getManagementKey(),
804 d);
805
806 validateId(prefix, "groupId", problems, Severity.ERROR, Version.BASE, d.getGroupId(), d.getManagementKey(), d);
807
808 if (!management) {
809 validateStringNotEmpty(
810 prefix, "type", problems, Severity.ERROR, Version.BASE, d.getType(), d.getManagementKey(), d);
811
812 validateDependencyVersion(problems, d, prefix);
813 }
814
815 if ("system".equals(d.getScope())) {
816 String systemPath = d.getSystemPath();
817
818 if (StringUtils.isEmpty(systemPath)) {
819 addViolation(
820 problems,
821 Severity.ERROR,
822 Version.BASE,
823 prefix + "systemPath",
824 d.getManagementKey(),
825 "is missing.",
826 d);
827 } else {
828 File sysFile = new File(systemPath);
829 if (!sysFile.isAbsolute()) {
830 addViolation(
831 problems,
832 Severity.ERROR,
833 Version.BASE,
834 prefix + "systemPath",
835 d.getManagementKey(),
836 "must specify an absolute path but is " + systemPath,
837 d);
838 } else if (!sysFile.isFile()) {
839 String msg = "refers to a non-existing file " + sysFile.getAbsolutePath();
840 systemPath = systemPath.replace('/', File.separatorChar).replace('\\', File.separatorChar);
841 String jdkHome =
842 request.getSystemProperties().getProperty("java.home", EMPTY) + File.separator + "..";
843 if (systemPath.startsWith(jdkHome)) {
844 msg += ". Please verify that you run Maven using a JDK and not just a JRE.";
845 }
846 addViolation(
847 problems,
848 Severity.WARNING,
849 Version.BASE,
850 prefix + "systemPath",
851 d.getManagementKey(),
852 msg,
853 d);
854 }
855 }
856 } else if (StringUtils.isNotEmpty(d.getSystemPath())) {
857 addViolation(
858 problems,
859 Severity.ERROR,
860 Version.BASE,
861 prefix + "systemPath",
862 d.getManagementKey(),
863 "must be omitted." + " This field may only be specified for a dependency with system scope.",
864 d);
865 }
866
867 if (request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
868 for (Exclusion exclusion : d.getExclusions()) {
869 if (request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0) {
870 validateId(
871 prefix,
872 "exclusions.exclusion.groupId",
873 problems,
874 Severity.WARNING,
875 Version.V20,
876 exclusion.getGroupId(),
877 d.getManagementKey(),
878 exclusion);
879
880 validateId(
881 prefix,
882 "exclusions.exclusion.artifactId",
883 problems,
884 Severity.WARNING,
885 Version.V20,
886 exclusion.getArtifactId(),
887 d.getManagementKey(),
888 exclusion);
889 } else {
890 validateIdWithWildcards(
891 prefix,
892 "exclusions.exclusion.groupId",
893 problems,
894 Severity.WARNING,
895 Version.V30,
896 exclusion.getGroupId(),
897 d.getManagementKey(),
898 exclusion);
899
900 validateIdWithWildcards(
901 prefix,
902 "exclusions.exclusion.artifactId",
903 problems,
904 Severity.WARNING,
905 Version.V30,
906 exclusion.getArtifactId(),
907 d.getManagementKey(),
908 exclusion);
909 }
910 }
911 }
912 }
913
914
915
916
917 protected void validateDependencyVersion(ModelProblemCollector problems, Dependency d, String prefix) {
918 validateStringNotEmpty(
919 prefix, "version", problems, Severity.ERROR, Version.BASE, d.getVersion(), d.getManagementKey(), d);
920 }
921
922 private void validateRawRepositories(
923 ModelProblemCollector problems,
924 List<Repository> repositories,
925 String prefix,
926 String prefix2,
927 ModelBuildingRequest request) {
928 Map<String, Repository> index = new HashMap<>();
929
930 for (Repository repository : repositories) {
931 validateStringNotEmpty(
932 prefix, prefix2, "id", problems, Severity.ERROR, Version.V20, repository.getId(), null, repository);
933
934 validateStringNotEmpty(
935 prefix,
936 prefix2,
937 "[" + repository.getId() + "].url",
938 problems,
939 Severity.ERROR,
940 Version.V20,
941 repository.getUrl(),
942 null,
943 repository);
944
945 String key = repository.getId();
946
947 Repository existing = index.get(key);
948
949 if (existing != null) {
950 Severity errOn30 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0);
951
952 addViolation(
953 problems,
954 errOn30,
955 Version.V20,
956 prefix + prefix2 + "id",
957 null,
958 "must be unique: " + repository.getId() + " -> " + existing.getUrl() + " vs "
959 + repository.getUrl(),
960 repository);
961 } else {
962 index.put(key, repository);
963 }
964 }
965 }
966
967 private void validate20EffectiveRepository(
968 ModelProblemCollector problems, Repository repository, String prefix, ModelBuildingRequest request) {
969 if (repository != null) {
970 Severity errOn31 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_1);
971
972 validateBannedCharacters(
973 prefix,
974 "id",
975 problems,
976 errOn31,
977 Version.V20,
978 repository.getId(),
979 null,
980 repository,
981 ILLEGAL_REPO_ID_CHARS);
982
983 if ("local".equals(repository.getId())) {
984 addViolation(
985 problems,
986 errOn31,
987 Version.V20,
988 prefix + "id",
989 null,
990 "must not be 'local'" + ", this identifier is reserved for the local repository"
991 + ", using it for other repositories will corrupt your repository metadata.",
992 repository);
993 }
994
995 if ("legacy".equals(repository.getLayout())) {
996 addViolation(
997 problems,
998 Severity.WARNING,
999 Version.V20,
1000 prefix + "layout",
1001 repository.getId(),
1002 "uses the unsupported value 'legacy', artifact resolution might fail.",
1003 repository);
1004 }
1005 }
1006 }
1007
1008 private void validate20RawResources(
1009 ModelProblemCollector problems, List<Resource> resources, String prefix, ModelBuildingRequest request) {
1010 Severity errOn30 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0);
1011
1012 for (Resource resource : resources) {
1013 validateStringNotEmpty(
1014 prefix,
1015 "directory",
1016 problems,
1017 Severity.ERROR,
1018 Version.V20,
1019 resource.getDirectory(),
1020 null,
1021 resource);
1022
1023 validateBoolean(
1024 prefix,
1025 "filtering",
1026 problems,
1027 errOn30,
1028 Version.V20,
1029 resource.getFiltering(),
1030 resource.getDirectory(),
1031 resource);
1032 }
1033 }
1034
1035
1036
1037
1038
1039 private boolean validateId(
1040 String fieldName, ModelProblemCollector problems, String id, InputLocationTracker tracker) {
1041 return validateId(EMPTY, fieldName, problems, Severity.ERROR, Version.BASE, id, null, tracker);
1042 }
1043
1044 @SuppressWarnings("checkstyle:parameternumber")
1045 private boolean validateId(
1046 String prefix,
1047 String fieldName,
1048 ModelProblemCollector problems,
1049 Severity severity,
1050 Version version,
1051 String id,
1052 String sourceHint,
1053 InputLocationTracker tracker) {
1054 if (validIds.contains(id)) {
1055 return true;
1056 }
1057 if (!validateStringNotEmpty(prefix, fieldName, problems, severity, version, id, sourceHint, tracker)) {
1058 return false;
1059 } else {
1060 if (!isValidId(id)) {
1061 addViolation(
1062 problems,
1063 severity,
1064 version,
1065 prefix + fieldName,
1066 sourceHint,
1067 "with value '" + id + "' does not match a valid id pattern.",
1068 tracker);
1069 return false;
1070 }
1071 validIds.add(id);
1072 return true;
1073 }
1074 }
1075
1076 private boolean isValidId(String id) {
1077 for (int i = 0; i < id.length(); i++) {
1078 char c = id.charAt(i);
1079 if (!isValidIdCharacter(c)) {
1080 return false;
1081 }
1082 }
1083 return true;
1084 }
1085
1086 private boolean isValidIdCharacter(char c) {
1087 return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '-' || c == '_' || c == '.';
1088 }
1089
1090 @SuppressWarnings("checkstyle:parameternumber")
1091 private boolean validateIdWithWildcards(
1092 String prefix,
1093 String fieldName,
1094 ModelProblemCollector problems,
1095 Severity severity,
1096 Version version,
1097 String id,
1098 String sourceHint,
1099 InputLocationTracker tracker) {
1100 if (!validateStringNotEmpty(prefix, fieldName, problems, severity, version, id, sourceHint, tracker)) {
1101 return false;
1102 } else {
1103 if (!isValidIdWithWildCards(id)) {
1104 addViolation(
1105 problems,
1106 severity,
1107 version,
1108 prefix + fieldName,
1109 sourceHint,
1110 "with value '" + id + "' does not match a valid id pattern.",
1111 tracker);
1112 return false;
1113 }
1114 return true;
1115 }
1116 }
1117
1118 private boolean isValidIdWithWildCards(String id) {
1119 for (int i = 0; i < id.length(); i++) {
1120 char c = id.charAt(i);
1121 if (!isValidIdWithWildCardCharacter(c)) {
1122 return false;
1123 }
1124 }
1125 return true;
1126 }
1127
1128 private boolean isValidIdWithWildCardCharacter(char c) {
1129 return isValidIdCharacter(c) || c == '?' || c == '*';
1130 }
1131
1132 private boolean validateStringNoExpression(
1133 String fieldName,
1134 ModelProblemCollector problems,
1135 Severity severity,
1136 Version version,
1137 String string,
1138 InputLocationTracker tracker) {
1139 if (!hasExpression(string)) {
1140 return true;
1141 }
1142
1143 addViolation(
1144 problems,
1145 severity,
1146 version,
1147 fieldName,
1148 null,
1149 "contains an expression but should be a constant.",
1150 tracker);
1151
1152 return false;
1153 }
1154
1155 private boolean validateVersionNoExpression(
1156 String fieldName,
1157 ModelProblemCollector problems,
1158 Severity severity,
1159 Version version,
1160 String string,
1161 InputLocationTracker tracker) {
1162 if (!hasExpression(string)) {
1163 return true;
1164 }
1165
1166 Matcher m = CI_FRIENDLY_EXPRESSION.matcher(string.trim());
1167 while (m.find()) {
1168 String property = m.group(1);
1169 if (!versionProcessor.isValidProperty(property)) {
1170 addViolation(
1171 problems,
1172 severity,
1173 version,
1174 fieldName,
1175 null,
1176 "contains an expression but should be a constant.",
1177 tracker);
1178 return false;
1179 }
1180 }
1181
1182 return true;
1183 }
1184
1185 private boolean hasExpression(String value) {
1186 return value != null && value.contains("${");
1187 }
1188
1189 private boolean hasProjectExpression(String value) {
1190 return value != null && value.contains("${project.");
1191 }
1192
1193 private boolean validateStringNotEmpty(
1194 String fieldName,
1195 ModelProblemCollector problems,
1196 Severity severity,
1197 Version version,
1198 String string,
1199 InputLocationTracker tracker) {
1200 return validateStringNotEmpty(EMPTY, fieldName, problems, severity, version, string, null, tracker);
1201 }
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211 @SuppressWarnings("checkstyle:parameternumber")
1212 private boolean validateStringNotEmpty(
1213 String prefix,
1214 String prefix2,
1215 String fieldName,
1216 ModelProblemCollector problems,
1217 Severity severity,
1218 Version version,
1219 String string,
1220 String sourceHint,
1221 InputLocationTracker tracker) {
1222 if (!validateNotNull(prefix, prefix2, fieldName, problems, severity, version, string, sourceHint, tracker)) {
1223 return false;
1224 }
1225
1226 if (!string.isEmpty()) {
1227 return true;
1228 }
1229
1230 addViolation(problems, severity, version, prefix + prefix2 + fieldName, sourceHint, "is missing.", tracker);
1231
1232 return false;
1233 }
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243 @SuppressWarnings("checkstyle:parameternumber")
1244 private boolean validateStringNotEmpty(
1245 String prefix,
1246 String fieldName,
1247 ModelProblemCollector problems,
1248 Severity severity,
1249 Version version,
1250 String string,
1251 String sourceHint,
1252 InputLocationTracker tracker) {
1253 if (!validateNotNull(prefix, fieldName, problems, severity, version, string, sourceHint, tracker)) {
1254 return false;
1255 }
1256
1257 if (string.length() > 0) {
1258 return true;
1259 }
1260
1261 addViolation(problems, severity, version, prefix + fieldName, sourceHint, "is missing.", tracker);
1262
1263 return false;
1264 }
1265
1266
1267
1268
1269
1270
1271
1272
1273 @SuppressWarnings("checkstyle:parameternumber")
1274 private boolean validateNotNull(
1275 String prefix,
1276 String fieldName,
1277 ModelProblemCollector problems,
1278 Severity severity,
1279 Version version,
1280 Object object,
1281 String sourceHint,
1282 InputLocationTracker tracker) {
1283 if (object != null) {
1284 return true;
1285 }
1286
1287 addViolation(problems, severity, version, prefix + fieldName, sourceHint, "is missing.", tracker);
1288
1289 return false;
1290 }
1291
1292
1293
1294
1295
1296
1297
1298
1299 @SuppressWarnings("checkstyle:parameternumber")
1300 private boolean validateNotNull(
1301 String prefix,
1302 String prefix2,
1303 String fieldName,
1304 ModelProblemCollector problems,
1305 Severity severity,
1306 Version version,
1307 Object object,
1308 String sourceHint,
1309 InputLocationTracker tracker) {
1310 if (object != null) {
1311 return true;
1312 }
1313
1314 addViolation(problems, severity, version, prefix + prefix2 + fieldName, sourceHint, "is missing.", tracker);
1315
1316 return false;
1317 }
1318
1319 @SuppressWarnings("checkstyle:parameternumber")
1320 private boolean validateBoolean(
1321 String prefix,
1322 String fieldName,
1323 ModelProblemCollector problems,
1324 Severity severity,
1325 Version version,
1326 String string,
1327 String sourceHint,
1328 InputLocationTracker tracker) {
1329 if (string == null || string.length() <= 0) {
1330 return true;
1331 }
1332
1333 if ("true".equalsIgnoreCase(string) || "false".equalsIgnoreCase(string)) {
1334 return true;
1335 }
1336
1337 addViolation(
1338 problems,
1339 severity,
1340 version,
1341 prefix + fieldName,
1342 sourceHint,
1343 "must be 'true' or 'false' but is '" + string + "'.",
1344 tracker);
1345
1346 return false;
1347 }
1348
1349 @SuppressWarnings("checkstyle:parameternumber")
1350 private boolean validateEnum(
1351 String prefix,
1352 String fieldName,
1353 ModelProblemCollector problems,
1354 Severity severity,
1355 Version version,
1356 String string,
1357 String sourceHint,
1358 InputLocationTracker tracker,
1359 String... validValues) {
1360 if (string == null || string.length() <= 0) {
1361 return true;
1362 }
1363
1364 List<String> values = Arrays.asList(validValues);
1365
1366 if (values.contains(string)) {
1367 return true;
1368 }
1369
1370 addViolation(
1371 problems,
1372 severity,
1373 version,
1374 prefix + fieldName,
1375 sourceHint,
1376 "must be one of " + values + " but is '" + string + "'.",
1377 tracker);
1378
1379 return false;
1380 }
1381
1382 @SuppressWarnings("checkstyle:parameternumber")
1383 private boolean validateModelVersion(
1384 ModelProblemCollector problems, String string, InputLocationTracker tracker, String... validVersions) {
1385 if (string == null || string.length() <= 0) {
1386 return true;
1387 }
1388
1389 List<String> values = Arrays.asList(validVersions);
1390
1391 if (values.contains(string)) {
1392 return true;
1393 }
1394
1395 boolean newerThanAll = true;
1396 boolean olderThanAll = true;
1397 for (String validValue : validVersions) {
1398 final int comparison = compareModelVersions(validValue, string);
1399 newerThanAll = newerThanAll && comparison < 0;
1400 olderThanAll = olderThanAll && comparison > 0;
1401 }
1402
1403 if (newerThanAll) {
1404 addViolation(
1405 problems,
1406 Severity.FATAL,
1407 Version.V20,
1408 "modelVersion",
1409 null,
1410 "of '" + string + "' is newer than the versions supported by this version of Maven: " + values
1411 + ". Building this project requires a newer version of Maven.",
1412 tracker);
1413
1414 } else if (olderThanAll) {
1415
1416 addViolation(
1417 problems,
1418 Severity.FATAL,
1419 Version.V20,
1420 "modelVersion",
1421 null,
1422 "of '" + string + "' is older than the versions supported by this version of Maven: " + values
1423 + ". Building this project requires an older version of Maven.",
1424 tracker);
1425
1426 } else {
1427 addViolation(
1428 problems,
1429 Severity.ERROR,
1430 Version.V20,
1431 "modelVersion",
1432 null,
1433 "must be one of " + values + " but is '" + string + "'.",
1434 tracker);
1435 }
1436
1437 return false;
1438 }
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448 private static int compareModelVersions(String first, String second) {
1449
1450 String[] firstSegments = StringUtils.split(first, ".");
1451 String[] secondSegments = StringUtils.split(second, ".");
1452 for (int i = 0; i < Math.min(firstSegments.length, secondSegments.length); i++) {
1453 int result = Long.valueOf(firstSegments[i]).compareTo(Long.valueOf(secondSegments[i]));
1454 if (result != 0) {
1455 return result;
1456 }
1457 }
1458 if (firstSegments.length == secondSegments.length) {
1459 return 0;
1460 }
1461 return firstSegments.length > secondSegments.length ? -1 : 1;
1462 }
1463
1464 @SuppressWarnings("checkstyle:parameternumber")
1465 private boolean validateBannedCharacters(
1466 String prefix,
1467 String fieldName,
1468 ModelProblemCollector problems,
1469 Severity severity,
1470 Version version,
1471 String string,
1472 String sourceHint,
1473 InputLocationTracker tracker,
1474 String banned) {
1475 if (string != null) {
1476 for (int i = string.length() - 1; i >= 0; i--) {
1477 if (banned.indexOf(string.charAt(i)) >= 0) {
1478 addViolation(
1479 problems,
1480 severity,
1481 version,
1482 prefix + fieldName,
1483 sourceHint,
1484 "must not contain any of these characters " + banned + " but found " + string.charAt(i),
1485 tracker);
1486 return false;
1487 }
1488 }
1489 }
1490
1491 return true;
1492 }
1493
1494 @SuppressWarnings("checkstyle:parameternumber")
1495 private boolean validateVersion(
1496 String prefix,
1497 String fieldName,
1498 ModelProblemCollector problems,
1499 Severity severity,
1500 Version version,
1501 String string,
1502 String sourceHint,
1503 InputLocationTracker tracker) {
1504 if (string == null || string.length() <= 0) {
1505 return true;
1506 }
1507
1508 if (hasExpression(string)) {
1509 addViolation(
1510 problems,
1511 severity,
1512 version,
1513 prefix + fieldName,
1514 sourceHint,
1515 "must be a valid version but is '" + string + "'.",
1516 tracker);
1517 return false;
1518 }
1519
1520 return validateBannedCharacters(
1521 prefix, fieldName, problems, severity, version, string, sourceHint, tracker, ILLEGAL_VERSION_CHARS);
1522 }
1523
1524 private boolean validate20ProperSnapshotVersion(
1525 String fieldName,
1526 ModelProblemCollector problems,
1527 Severity severity,
1528 Version version,
1529 String string,
1530 String sourceHint,
1531 InputLocationTracker tracker) {
1532 if (string == null || string.length() <= 0) {
1533 return true;
1534 }
1535
1536 if (string.endsWith("SNAPSHOT") && !string.endsWith("-SNAPSHOT")) {
1537 addViolation(
1538 problems,
1539 severity,
1540 version,
1541 fieldName,
1542 sourceHint,
1543 "uses an unsupported snapshot version format, should be '*-SNAPSHOT' instead.",
1544 tracker);
1545 return false;
1546 }
1547
1548 return true;
1549 }
1550
1551 private boolean validate20PluginVersion(
1552 String fieldName,
1553 ModelProblemCollector problems,
1554 String string,
1555 String sourceHint,
1556 InputLocationTracker tracker,
1557 ModelBuildingRequest request) {
1558 if (string == null) {
1559
1560 return true;
1561 }
1562
1563 Severity errOn30 = getSeverity(request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0);
1564
1565 if (!validateVersion(EMPTY, fieldName, problems, errOn30, Version.V20, string, sourceHint, tracker)) {
1566 return false;
1567 }
1568
1569 if (string.length() <= 0 || "RELEASE".equals(string) || "LATEST".equals(string)) {
1570 addViolation(
1571 problems,
1572 errOn30,
1573 Version.V20,
1574 fieldName,
1575 sourceHint,
1576 "must be a valid version but is '" + string + "'.",
1577 tracker);
1578 return false;
1579 }
1580
1581 return true;
1582 }
1583
1584 private static void addViolation(
1585 ModelProblemCollector problems,
1586 Severity severity,
1587 Version version,
1588 String fieldName,
1589 String sourceHint,
1590 String message,
1591 InputLocationTracker tracker) {
1592 StringBuilder buffer = new StringBuilder(256);
1593 buffer.append('\'').append(fieldName).append('\'');
1594
1595 if (sourceHint != null) {
1596 buffer.append(" for ").append(sourceHint);
1597 }
1598
1599 buffer.append(' ').append(message);
1600
1601
1602 problems.add(new ModelProblemCollectorRequest(severity, version)
1603 .setMessage(buffer.toString())
1604 .setLocation(getLocation(fieldName, tracker)));
1605
1606 }
1607
1608 private static InputLocation getLocation(String fieldName, InputLocationTracker tracker) {
1609 InputLocation location = null;
1610
1611 if (tracker != null) {
1612 if (fieldName != null) {
1613 Object key = fieldName;
1614
1615 int idx = fieldName.lastIndexOf('.');
1616 if (idx >= 0) {
1617 fieldName = fieldName.substring(idx + 1);
1618 key = fieldName;
1619 }
1620
1621 if (fieldName.endsWith("]")) {
1622 key = fieldName.substring(fieldName.lastIndexOf('[') + 1, fieldName.length() - 1);
1623 try {
1624 key = Integer.valueOf(key.toString());
1625 } catch (NumberFormatException e) {
1626
1627 }
1628 }
1629
1630 location = tracker.getLocation(key);
1631 }
1632
1633 if (location == null) {
1634 location = tracker.getLocation(EMPTY);
1635 }
1636 }
1637
1638 return location;
1639 }
1640
1641 private static boolean equals(String s1, String s2) {
1642 return StringUtils.clean(s1).equals(StringUtils.clean(s2));
1643 }
1644
1645 private static Severity getSeverity(ModelBuildingRequest request, int errorThreshold) {
1646 return getSeverity(request.getValidationLevel(), errorThreshold);
1647 }
1648
1649 private static Severity getSeverity(int validationLevel, int errorThreshold) {
1650 if (validationLevel < errorThreshold) {
1651 return Severity.WARNING;
1652 } else {
1653 return Severity.ERROR;
1654 }
1655 }
1656 }