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     * @deprecated the visibility will be reduced to private with the next major version
052     * @see {@link #setBanRepositories(boolean)}
053     */
054    public boolean banRepositories = true;
055
056    /**
057     * Whether to ban plugin repositories. By default they are banned.
058     * 
059     * @deprecated the visibility will be reduced to private with the next major version
060     * @see {@link #setBanPluginRepositories(boolean)}
061     */
062    public boolean banPluginRepositories = true;
063
064    /**
065     * Specify explicitly allowed non-plugin repositories. This is a list of ids.
066     * 
067     * @deprecated the visibility will be reduced to private with the next major version
068     * @see {@link #setAllowedRepositories(List)}
069     */
070    public List<String> allowedRepositories = Collections.emptyList();
071
072    /**
073     * Specify explicitly allowed plugin repositories. This is a list of ids.
074     * 
075     * @deprecated the visibility will be reduced to private with the next major version
076     * @see {@link #setAllowedPluginRepositories(List)}
077     */
078    public List<String> allowedPluginRepositories = Collections.emptyList();
079
080    /**
081     * Whether to allow repositories which only resolve snapshots. By default they are banned.
082     * 
083     * @deprecated the visibility will be reduced to private with the next major version
084     * @see {@link #setAllowSnapshotRepositories(boolean)}
085     */
086    public boolean allowSnapshotRepositories = false;
087
088    /**
089     * Whether to allow plugin repositories which only resolve snapshots. By default they are banned.
090     * 
091     * @deprecated the visibility will be reduced to private with the next major version
092     * @see {@link #setAllowSnapshotPluginRepositories(boolean)}
093     */
094    public boolean allowSnapshotPluginRepositories = false;
095
096    public final void setBanRepositories( boolean banRepositories )
097    {
098        this.banRepositories = banRepositories;
099    }
100    
101    public final void setBanPluginRepositories( boolean banPluginRepositories )
102    {
103        this.banPluginRepositories = banPluginRepositories;
104    }
105    
106    public final void setAllowedRepositories( List<String> allowedRepositories )
107    {
108        this.allowedRepositories = allowedRepositories;
109    }
110    
111    public final void setAllowedPluginRepositories( List<String> allowedPluginRepositories )
112    {
113        this.allowedPluginRepositories = allowedPluginRepositories;
114    }
115    
116    public final void setAllowSnapshotRepositories( boolean allowSnapshotRepositories )
117    {
118        this.allowSnapshotRepositories = allowSnapshotRepositories;
119    }
120    
121    public final void setAllowSnapshotPluginRepositories( boolean allowSnapshotPluginRepositories )
122    {
123        this.allowSnapshotPluginRepositories = allowSnapshotPluginRepositories;
124    }
125    
126    /*
127     * (non-Javadoc)
128     * @see
129     * org.apache.maven.enforcer.rule.api.EnforcerRule#execute(org.apache.maven.enforcer.rule.api.EnforcerRuleHelper)
130     */
131    public void execute( EnforcerRuleHelper helper )
132        throws EnforcerRuleException
133    {
134        EnforcerRuleUtils utils = new EnforcerRuleUtils( helper );
135
136        MavenProject project;
137        try
138        {
139            project = (MavenProject) helper.evaluate( "${project}" );
140
141            List<Model> models =
142                utils.getModelsRecursively( project.getGroupId(), project.getArtifactId(), project.getVersion(),
143                                            new File( project.getBasedir(), "pom.xml" ) );
144            List<Model> badModels = new ArrayList<Model>();
145
146            StringBuffer newMsg = new StringBuffer();
147            newMsg.append( "Some poms have repositories defined:\n" );
148
149            for ( Model model : models )
150            {
151                if ( banRepositories )
152                {
153                    @SuppressWarnings( "unchecked" )
154                    List<Repository> repos = model.getRepositories();
155                    if ( repos != null && !repos.isEmpty() )
156                    {
157                        List<String> bannedRepos =
158                            findBannedRepositories( repos, allowedRepositories, allowSnapshotRepositories );
159                        if ( !bannedRepos.isEmpty() )
160                        {
161                            badModels.add( model );
162                            newMsg.append(
163                                model.getGroupId() + ":" + model.getArtifactId() + " version:" + model.getVersion()
164                                    + " has repositories " + bannedRepos );
165                        }
166                    }
167                }
168                if ( banPluginRepositories )
169                {
170                    @SuppressWarnings( "unchecked" )
171                    List<Repository> repos = model.getPluginRepositories();
172                    if ( repos != null && !repos.isEmpty() )
173                    {
174                        List<String> bannedRepos =
175                            findBannedRepositories( repos, allowedPluginRepositories, allowSnapshotPluginRepositories );
176                        if ( !bannedRepos.isEmpty() )
177                        {
178                            badModels.add( model );
179                            newMsg.append(
180                                model.getGroupId() + ":" + model.getArtifactId() + " version:" + model.getVersion()
181                                    + " has plugin repositories " + bannedRepos );
182                        }
183                    }
184                }
185            }
186
187            // if anything was found, log it then append the
188            // optional message.
189            if ( !badModels.isEmpty() )
190            {
191                String message = getMessage();
192                if ( StringUtils.isNotEmpty( message ) )
193                {
194                    newMsg.append( message );
195                }
196
197                throw new EnforcerRuleException( newMsg.toString() );
198            }
199
200        }
201        catch ( ExpressionEvaluationException e )
202        {
203            throw new EnforcerRuleException( e.getLocalizedMessage() );
204        }
205        catch ( ArtifactResolutionException e )
206        {
207            throw new EnforcerRuleException( e.getLocalizedMessage() );
208        }
209        catch ( ArtifactNotFoundException e )
210        {
211            throw new EnforcerRuleException( e.getLocalizedMessage() );
212        }
213        catch ( IOException e )
214        {
215            throw new EnforcerRuleException( e.getLocalizedMessage() );
216        }
217        catch ( XmlPullParserException e )
218        {
219            throw new EnforcerRuleException( e.getLocalizedMessage() );
220        }
221    }
222
223    /**
224     * 
225     * @param repos all repositories, never {@code null}
226     * @param allowedRepos allowed repositories, never {@code null}
227     * @param allowSnapshots 
228     * @return
229     */
230    private static List<String> findBannedRepositories( List<Repository> repos, List<String> allowedRepos, boolean allowSnapshots )
231    {
232        List<String> bannedRepos = new ArrayList<String>( allowedRepos.size() );
233        for ( Repository r : repos )
234        {
235            if ( !allowedRepos.contains( r.getId() ) )
236            {
237                if ( !allowSnapshots || r.getReleases() == null || r.getReleases().isEnabled() )
238                {
239                    // if we are not allowing snapshots and this repo is enabled for releases
240                    // it is banned.  We don't care whether it is enabled for snapshots
241                    // if you define a repo and don't enable it for anything, then we have nothing 
242                    // to worry about
243                    bannedRepos.add( r.getId() );
244                }
245            }
246        }
247        return bannedRepos;
248    }
249}