View Javadoc
1   package org.apache.maven.settings.validation;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.HashSet;
23  import java.util.List;
24  import java.util.Set;
25  
26  import org.apache.maven.settings.Mirror;
27  import org.apache.maven.settings.Profile;
28  import org.apache.maven.settings.Repository;
29  import org.apache.maven.settings.Server;
30  import org.apache.maven.settings.Settings;
31  import org.apache.maven.settings.building.SettingsProblem.Severity;
32  import org.apache.maven.settings.building.SettingsProblemCollector;
33  import org.codehaus.plexus.component.annotations.Component;
34  import org.codehaus.plexus.util.StringUtils;
35  
36  /**
37   * @author Milos Kleint
38   */
39  @Component( role = SettingsValidator.class )
40  public class DefaultSettingsValidator
41      implements SettingsValidator
42  {
43  
44      private static final String ID_REGEX = "[A-Za-z0-9_\\-.]+";
45  
46      private static final String ILLEGAL_FS_CHARS = "\\/:\"<>|?*";
47  
48      private static final String ILLEGAL_REPO_ID_CHARS = ILLEGAL_FS_CHARS;
49  
50      @Override
51      public void validate( Settings settings, SettingsProblemCollector problems )
52      {
53          if ( settings.isUsePluginRegistry() )
54          {
55              addViolation( problems, Severity.WARNING, "usePluginRegistry", null, "is deprecated and has no effect." );
56          }
57  
58          List<String> pluginGroups = settings.getPluginGroups();
59  
60          if ( pluginGroups != null )
61          {
62              for ( int i = 0; i < pluginGroups.size(); i++ )
63              {
64                  String pluginGroup = pluginGroups.get( i ).trim();
65  
66                  if ( StringUtils.isBlank( pluginGroup ) )
67                  {
68                      addViolation( problems, Severity.ERROR, "pluginGroups.pluginGroup[" + i + "]", null,
69                                    "must not be empty" );
70                  }
71                  else if ( !pluginGroup.matches( ID_REGEX ) )
72                  {
73                      addViolation( problems, Severity.ERROR, "pluginGroups.pluginGroup[" + i + "]", null,
74                                    "must denote a valid group id and match the pattern " + ID_REGEX );
75                  }
76              }
77          }
78  
79          List<Server> servers = settings.getServers();
80  
81          if ( servers != null )
82          {
83              Set<String> serverIds = new HashSet<String>();
84  
85              for ( int i = 0; i < servers.size(); i++ )
86              {
87                  Server server = servers.get( i );
88  
89                  validateStringNotEmpty( problems, "servers.server[" + i + "].id", server.getId(), null );
90  
91                  if ( !serverIds.add( server.getId() ) )
92                  {
93                      addViolation( problems, Severity.WARNING, "servers.server.id", null,
94                                    "must be unique but found duplicate server with id " + server.getId() );
95                  }
96              }
97          }
98  
99          List<Mirror> mirrors = settings.getMirrors();
100 
101         if ( mirrors != null )
102         {
103             for ( Mirror mirror : mirrors )
104             {
105                 validateStringNotEmpty( problems, "mirrors.mirror.id", mirror.getId(), mirror.getUrl() );
106 
107                 validateBannedCharacters( problems, "mirrors.mirror.id", Severity.WARNING, mirror.getId(), null,
108                                           ILLEGAL_REPO_ID_CHARS );
109 
110                 if ( "local".equals( mirror.getId() ) )
111                 {
112                     addViolation( problems, Severity.WARNING, "mirrors.mirror.id", null, "must not be 'local'"
113                         + ", this identifier is reserved for the local repository"
114                         + ", using it for other repositories will corrupt your repository metadata." );
115                 }
116 
117                 validateStringNotEmpty( problems, "mirrors.mirror.url", mirror.getUrl(), mirror.getId() );
118 
119                 validateStringNotEmpty( problems, "mirrors.mirror.mirrorOf", mirror.getMirrorOf(), mirror.getId() );
120             }
121         }
122 
123         List<Profile> profiles = settings.getProfiles();
124 
125         if ( profiles != null )
126         {
127             Set<String> profileIds = new HashSet<String>();
128 
129             for ( Profile profile : profiles )
130             {
131                 if ( !profileIds.add( profile.getId() ) )
132                 {
133                     addViolation( problems, Severity.WARNING, "profiles.profile.id", null,
134                                   "must be unique but found duplicate profile with id " + profile.getId() );
135                 }
136 
137                 String prefix = "profiles.profile[" + profile.getId() + "].";
138 
139                 validateRepositories( problems, profile.getRepositories(), prefix + "repositories.repository" );
140                 validateRepositories( problems, profile.getPluginRepositories(), prefix
141                     + "pluginRepositories.pluginRepository" );
142             }
143         }
144     }
145 
146     private void validateRepositories( SettingsProblemCollector problems, List<Repository> repositories, String prefix )
147     {
148         Set<String> repoIds = new HashSet<String>();
149 
150         for ( Repository repository : repositories )
151         {
152             validateStringNotEmpty( problems, prefix + ".id", repository.getId(), repository.getUrl() );
153 
154             validateBannedCharacters( problems, prefix + ".id", Severity.WARNING, repository.getId(), null,
155                                       ILLEGAL_REPO_ID_CHARS );
156 
157             if ( "local".equals( repository.getId() ) )
158             {
159                 addViolation( problems, Severity.WARNING, prefix + ".id", null, "must not be 'local'"
160                     + ", this identifier is reserved for the local repository"
161                     + ", using it for other repositories will corrupt your repository metadata." );
162             }
163 
164             if ( !repoIds.add( repository.getId() ) )
165             {
166                 addViolation( problems, Severity.WARNING, prefix + ".id", null,
167                               "must be unique but found duplicate repository with id " + repository.getId() );
168             }
169 
170             validateStringNotEmpty( problems, prefix + ".url", repository.getUrl(), repository.getId() );
171 
172             if ( "legacy".equals( repository.getLayout() ) )
173             {
174                 addViolation( problems, Severity.WARNING, prefix + ".layout", repository.getId(),
175                               "uses the unsupported value 'legacy', artifact resolution might fail." );
176             }
177         }
178     }
179 
180     // ----------------------------------------------------------------------
181     // Field validation
182     // ----------------------------------------------------------------------
183 
184     /**
185      * Asserts:
186      * <p/>
187      * <ul>
188      * <li><code>string.length != null</code>
189      * <li><code>string.length > 0</code>
190      * </ul>
191      */
192     private boolean validateStringNotEmpty( SettingsProblemCollector problems, String fieldName, String string,
193                                             String sourceHint )
194     {
195         if ( !validateNotNull( problems, fieldName, string, sourceHint ) )
196         {
197             return false;
198         }
199 
200         if ( string.length() > 0 )
201         {
202             return true;
203         }
204 
205         addViolation( problems, Severity.ERROR, fieldName, sourceHint, "is missing" );
206 
207         return false;
208     }
209 
210     /**
211      * Asserts:
212      * <p/>
213      * <ul>
214      * <li><code>string != null</code>
215      * </ul>
216      */
217     private boolean validateNotNull( SettingsProblemCollector problems, String fieldName, Object object,
218                                      String sourceHint )
219     {
220         if ( object != null )
221         {
222             return true;
223         }
224 
225         addViolation( problems, Severity.ERROR, fieldName, sourceHint, "is missing" );
226 
227         return false;
228     }
229 
230     private boolean validateBannedCharacters( SettingsProblemCollector problems, String fieldName, Severity severity,
231                                               String string, String sourceHint, String banned )
232     {
233         if ( string != null )
234         {
235             for ( int i = string.length() - 1; i >= 0; i-- )
236             {
237                 if ( banned.indexOf( string.charAt( i ) ) >= 0 )
238                 {
239                     addViolation( problems, severity, fieldName, sourceHint,
240                                   "must not contain any of these characters " + banned + " but found "
241                                       + string.charAt( i ) );
242                     return false;
243                 }
244             }
245         }
246 
247         return true;
248     }
249 
250     private void addViolation( SettingsProblemCollector problems, Severity severity, String fieldName,
251                                String sourceHint, String message )
252     {
253         StringBuilder buffer = new StringBuilder( 256 );
254         buffer.append( '\'' ).append( fieldName ).append( '\'' );
255 
256         if ( sourceHint != null )
257         {
258             buffer.append( " for " ).append( sourceHint );
259         }
260 
261         buffer.append( ' ' ).append( message );
262 
263         problems.add( severity, buffer.toString(), -1, -1, null );
264     }
265 
266 }