1 package org.apache.maven.settings.validation;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Set;
25
26 import javax.inject.Named;
27 import javax.inject.Singleton;
28
29 import org.apache.maven.settings.Mirror;
30 import org.apache.maven.settings.Profile;
31 import org.apache.maven.settings.Repository;
32 import org.apache.maven.settings.Proxy;
33 import org.apache.maven.settings.Server;
34 import org.apache.maven.settings.Settings;
35 import org.apache.maven.settings.building.SettingsProblem.Severity;
36 import org.apache.maven.settings.building.SettingsProblemCollector;
37 import org.codehaus.plexus.util.StringUtils;
38
39
40
41
42 @Named
43 @Singleton
44 public class DefaultSettingsValidator
45 implements SettingsValidator
46 {
47
48 private static final String ID_REGEX = "[A-Za-z0-9_\\-.]+";
49
50 private static final String ILLEGAL_FS_CHARS = "\\/:\"<>|?*";
51
52 private static final String ILLEGAL_REPO_ID_CHARS = ILLEGAL_FS_CHARS;
53
54 @Override
55 public void validate( Settings settings, SettingsProblemCollector problems )
56 {
57 if ( settings.isUsePluginRegistry() )
58 {
59 addViolation( problems, Severity.WARNING, "usePluginRegistry", null, "is deprecated and has no effect." );
60 }
61
62 List<String> pluginGroups = settings.getPluginGroups();
63
64 if ( pluginGroups != null )
65 {
66 for ( int i = 0; i < pluginGroups.size(); i++ )
67 {
68 String pluginGroup = pluginGroups.get( i ).trim();
69
70 if ( StringUtils.isBlank( pluginGroup ) )
71 {
72 addViolation( problems, Severity.ERROR, "pluginGroups.pluginGroup[" + i + "]", null,
73 "must not be empty" );
74 }
75 else if ( !pluginGroup.matches( ID_REGEX ) )
76 {
77 addViolation( problems, Severity.ERROR, "pluginGroups.pluginGroup[" + i + "]", null,
78 "must denote a valid group id and match the pattern " + ID_REGEX );
79 }
80 }
81 }
82
83 List<Server> servers = settings.getServers();
84
85 if ( servers != null )
86 {
87 Set<String> serverIds = new HashSet<>();
88
89 for ( int i = 0; i < servers.size(); i++ )
90 {
91 Server server = servers.get( i );
92
93 validateStringNotEmpty( problems, "servers.server[" + i + "].id", server.getId(), null );
94
95 if ( !serverIds.add( server.getId() ) )
96 {
97 addViolation( problems, Severity.WARNING, "servers.server.id", null,
98 "must be unique but found duplicate server with id " + server.getId() );
99 }
100 }
101 }
102
103 List<Mirror> mirrors = settings.getMirrors();
104
105 if ( mirrors != null )
106 {
107 for ( Mirror mirror : mirrors )
108 {
109 validateStringNotEmpty( problems, "mirrors.mirror.id", mirror.getId(), mirror.getUrl() );
110
111 validateBannedCharacters( problems, "mirrors.mirror.id", Severity.WARNING, mirror.getId(), null,
112 ILLEGAL_REPO_ID_CHARS );
113
114 if ( "local".equals( mirror.getId() ) )
115 {
116 addViolation( problems, Severity.WARNING, "mirrors.mirror.id", null, "must not be 'local'"
117 + ", this identifier is reserved for the local repository"
118 + ", using it for other repositories will corrupt your repository metadata." );
119 }
120
121 validateStringNotEmpty( problems, "mirrors.mirror.url", mirror.getUrl(), mirror.getId() );
122
123 validateStringNotEmpty( problems, "mirrors.mirror.mirrorOf", mirror.getMirrorOf(), mirror.getId() );
124 }
125 }
126
127 List<Profile> profiles = settings.getProfiles();
128
129 if ( profiles != null )
130 {
131 Set<String> profileIds = new HashSet<>();
132
133 for ( Profile profile : profiles )
134 {
135 if ( !profileIds.add( profile.getId() ) )
136 {
137 addViolation( problems, Severity.WARNING, "profiles.profile.id", null,
138 "must be unique but found duplicate profile with id " + profile.getId() );
139 }
140
141 String prefix = "profiles.profile[" + profile.getId() + "].";
142
143 validateRepositories( problems, profile.getRepositories(), prefix + "repositories.repository" );
144 validateRepositories( problems, profile.getPluginRepositories(), prefix
145 + "pluginRepositories.pluginRepository" );
146 }
147 }
148
149 List<Proxy> proxies = settings.getProxies();
150
151 if ( proxies != null )
152 {
153 Set<String> proxyIds = new HashSet<>();
154
155 for ( Proxy proxy : proxies )
156 {
157 if ( !proxyIds.add( proxy.getId() ) )
158 {
159 addViolation( problems, Severity.WARNING, "proxies.proxy.id", null,
160 "must be unique but found duplicate proxy with id " + proxy.getId() );
161 }
162 validateStringNotEmpty( problems, "proxies.proxy.host", proxy.getHost(), proxy.getId() );
163 }
164 }
165 }
166
167 private void validateRepositories( SettingsProblemCollector problems, List<Repository> repositories, String prefix )
168 {
169 Set<String> repoIds = new HashSet<>();
170
171 for ( Repository repository : repositories )
172 {
173 validateStringNotEmpty( problems, prefix + ".id", repository.getId(), repository.getUrl() );
174
175 validateBannedCharacters( problems, prefix + ".id", Severity.WARNING, repository.getId(), null,
176 ILLEGAL_REPO_ID_CHARS );
177
178 if ( "local".equals( repository.getId() ) )
179 {
180 addViolation( problems, Severity.WARNING, prefix + ".id", null, "must not be 'local'"
181 + ", this identifier is reserved for the local repository"
182 + ", using it for other repositories will corrupt your repository metadata." );
183 }
184
185 if ( !repoIds.add( repository.getId() ) )
186 {
187 addViolation( problems, Severity.WARNING, prefix + ".id", null,
188 "must be unique but found duplicate repository with id " + repository.getId() );
189 }
190
191 validateStringNotEmpty( problems, prefix + ".url", repository.getUrl(), repository.getId() );
192
193 if ( "legacy".equals( repository.getLayout() ) )
194 {
195 addViolation( problems, Severity.WARNING, prefix + ".layout", repository.getId(),
196 "uses the unsupported value 'legacy', artifact resolution might fail." );
197 }
198 }
199 }
200
201
202
203
204
205
206
207
208
209
210
211
212
213 private static boolean validateStringNotEmpty( SettingsProblemCollector problems, String fieldName, String string,
214 String sourceHint )
215 {
216 if ( !validateNotNull( problems, fieldName, string, sourceHint ) )
217 {
218 return false;
219 }
220
221 if ( string.length() > 0 )
222 {
223 return true;
224 }
225
226 addViolation( problems, Severity.ERROR, fieldName, sourceHint, "is missing" );
227
228 return false;
229 }
230
231
232
233
234
235
236
237
238 private static boolean validateNotNull( SettingsProblemCollector problems, String fieldName, Object object,
239 String sourceHint )
240 {
241 if ( object != null )
242 {
243 return true;
244 }
245
246 addViolation( problems, Severity.ERROR, fieldName, sourceHint, "is missing" );
247
248 return false;
249 }
250
251 private static boolean validateBannedCharacters( SettingsProblemCollector problems, String fieldName,
252 Severity severity, String string, String sourceHint,
253 String banned )
254 {
255 if ( string != null )
256 {
257 for ( int i = string.length() - 1; i >= 0; i-- )
258 {
259 if ( banned.indexOf( string.charAt( i ) ) >= 0 )
260 {
261 addViolation( problems, severity, fieldName, sourceHint,
262 "must not contain any of these characters " + banned + " but found "
263 + string.charAt( i ) );
264 return false;
265 }
266 }
267 }
268
269 return true;
270 }
271
272 private static void addViolation( SettingsProblemCollector problems, Severity severity, String fieldName,
273 String sourceHint, String message )
274 {
275 StringBuilder buffer = new StringBuilder( 256 );
276 buffer.append( '\'' ).append( fieldName ).append( '\'' );
277
278 if ( sourceHint != null )
279 {
280 buffer.append( " for " ).append( sourceHint );
281 }
282
283 buffer.append( ' ' ).append( message );
284
285 problems.add( severity, buffer.toString(), -1, -1, null );
286 }
287
288 }