001package org.apache.maven.plugins.enforcer;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.File;
023import java.io.IOException;
024import java.util.ArrayList;
025import java.util.Collections;
026import java.util.List;
027
028import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
029import org.apache.maven.artifact.resolver.ArtifactResolutionException;
030import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
031import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
032import org.apache.maven.model.Model;
033import org.apache.maven.model.Repository;
034import org.apache.maven.plugins.enforcer.utils.EnforcerRuleUtils;
035import org.apache.maven.project.MavenProject;
036import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
037import org.codehaus.plexus.util.StringUtils;
038import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
039
040/**
041 * This rule checks that this pom or its parents don't define a repository.
042 *
043 * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
044 */
045public class RequireNoRepositories
046    extends AbstractNonCacheableEnforcerRule
047{
048    /**
049     * Whether to ban non-plugin repositories. By default they are banned.
050     * 
051     * @see {@link #setBanRepositories(boolean)}
052     */
053    private boolean banRepositories = true;
054
055    /**
056     * Whether to ban plugin repositories. By default they are banned.
057     * 
058     * @see {@link #setBanPluginRepositories(boolean)}
059     */
060    private boolean banPluginRepositories = true;
061
062    /**
063     * Specify explicitly allowed non-plugin repositories. This is a list of ids.
064     * 
065     * @see {@link #setAllowedRepositories(List)}
066     */
067    private List<String> allowedRepositories = Collections.emptyList();
068
069    /**
070     * Specify explicitly allowed plugin repositories. This is a list of ids.
071     * 
072     * @see {@link #setAllowedPluginRepositories(List)}
073     */
074    private List<String> allowedPluginRepositories = Collections.emptyList();
075
076    /**
077     * Whether to allow repositories which only resolve snapshots. By default they are banned.
078     * 
079     * @see {@link #setAllowSnapshotRepositories(boolean)}
080     */
081    private boolean allowSnapshotRepositories = false;
082
083    /**
084     * Whether to allow plugin repositories which only resolve snapshots. By default they are banned.
085     * 
086     * @see {@link #setAllowSnapshotPluginRepositories(boolean)}
087     */
088    private boolean allowSnapshotPluginRepositories = false;
089
090    public final void setBanRepositories( boolean banRepositories )
091    {
092        this.banRepositories = banRepositories;
093    }
094    
095    public final void setBanPluginRepositories( boolean banPluginRepositories )
096    {
097        this.banPluginRepositories = banPluginRepositories;
098    }
099    
100    public final void setAllowedRepositories( List<String> allowedRepositories )
101    {
102        this.allowedRepositories = allowedRepositories;
103    }
104    
105    public final void setAllowedPluginRepositories( List<String> allowedPluginRepositories )
106    {
107        this.allowedPluginRepositories = allowedPluginRepositories;
108    }
109    
110    public final void setAllowSnapshotRepositories( boolean allowSnapshotRepositories )
111    {
112        this.allowSnapshotRepositories = allowSnapshotRepositories;
113    }
114    
115    public final void setAllowSnapshotPluginRepositories( boolean allowSnapshotPluginRepositories )
116    {
117        this.allowSnapshotPluginRepositories = allowSnapshotPluginRepositories;
118    }
119    
120    /**
121     * {@inheritDoc}
122     */
123    public void execute( EnforcerRuleHelper helper )
124        throws EnforcerRuleException
125    {
126        EnforcerRuleUtils utils = new EnforcerRuleUtils( helper );
127
128        MavenProject project;
129        try
130        {
131            project = (MavenProject) helper.evaluate( "${project}" );
132
133            List<Model> models =
134                utils.getModelsRecursively( project.getGroupId(), project.getArtifactId(), project.getVersion(),
135                                            new File( project.getBasedir(), "pom.xml" ) );
136            List<Model> badModels = new ArrayList<Model>();
137
138            StringBuffer newMsg = new StringBuffer();
139            newMsg.append( "Some poms have repositories defined:\n" );
140
141            for ( Model model : models )
142            {
143                if ( banRepositories )
144                {
145                    List<Repository> repos = model.getRepositories();
146                    if ( repos != null && !repos.isEmpty() )
147                    {
148                        List<String> bannedRepos =
149                            findBannedRepositories( repos, allowedRepositories, allowSnapshotRepositories );
150                        if ( !bannedRepos.isEmpty() )
151                        {
152                            badModels.add( model );
153                            newMsg.append(
154                                model.getGroupId() + ":" + model.getArtifactId() + " version:" + model.getVersion()
155                                    + " has repositories " + bannedRepos );
156                        }
157                    }
158                }
159                if ( banPluginRepositories )
160                {
161                    List<Repository> repos = model.getPluginRepositories();
162                    if ( repos != null && !repos.isEmpty() )
163                    {
164                        List<String> bannedRepos =
165                            findBannedRepositories( repos, allowedPluginRepositories, allowSnapshotPluginRepositories );
166                        if ( !bannedRepos.isEmpty() )
167                        {
168                            badModels.add( model );
169                            newMsg.append(
170                                model.getGroupId() + ":" + model.getArtifactId() + " version:" + model.getVersion()
171                                    + " has plugin repositories " + bannedRepos );
172                        }
173                    }
174                }
175            }
176
177            // if anything was found, log it then append the
178            // optional message.
179            if ( !badModels.isEmpty() )
180            {
181                String message = getMessage();
182                if ( StringUtils.isNotEmpty( message ) )
183                {
184                    newMsg.append( message );
185                }
186
187                throw new EnforcerRuleException( newMsg.toString() );
188            }
189
190        }
191        catch ( ExpressionEvaluationException e )
192        {
193            throw new EnforcerRuleException( e.getLocalizedMessage() );
194        }
195        catch ( ArtifactResolutionException e )
196        {
197            throw new EnforcerRuleException( e.getLocalizedMessage() );
198        }
199        catch ( ArtifactNotFoundException e )
200        {
201            throw new EnforcerRuleException( e.getLocalizedMessage() );
202        }
203        catch ( IOException e )
204        {
205            throw new EnforcerRuleException( e.getLocalizedMessage() );
206        }
207        catch ( XmlPullParserException e )
208        {
209            throw new EnforcerRuleException( e.getLocalizedMessage() );
210        }
211    }
212
213    /**
214     * 
215     * @param repos all repositories, never {@code null}
216     * @param allowedRepos allowed repositories, never {@code null}
217     * @param allowSnapshots 
218     * @return
219     */
220    private static List<String> findBannedRepositories( List<Repository> repos, List<String> allowedRepos,
221                                                        boolean allowSnapshots )
222    {
223        List<String> bannedRepos = new ArrayList<String>( allowedRepos.size() );
224        for ( Repository r : repos )
225        {
226            if ( !allowedRepos.contains( r.getId() ) )
227            {
228                if ( !allowSnapshots || r.getReleases() == null || r.getReleases().isEnabled() )
229                {
230                    // if we are not allowing snapshots and this repo is enabled for releases
231                    // it is banned.  We don't care whether it is enabled for snapshots
232                    // if you define a repo and don't enable it for anything, then we have nothing 
233                    // to worry about
234                    bannedRepos.add( r.getId() );
235                }
236            }
237        }
238        return bannedRepos;
239    }
240}