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