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