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.util.ArrayList;
023import java.util.Collections;
024import java.util.List;
025
026import org.apache.maven.artifact.repository.ArtifactRepository;
027import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
028import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
029import org.apache.maven.project.MavenProject;
030import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
031import org.codehaus.plexus.util.StringUtils;
032
033/**
034 * This rule checks that this project's maven session whether have banned repositories.
035 * 
036 * @author <a href="mailto:wangyf2010@gmail.com">Simon Wang</a>
037 */
038public class BannedRepositories
039    extends AbstractNonCacheableEnforcerRule
040{
041
042    // ----------------------------------------------------------------------
043    // Mojo parameters
044    // ----------------------------------------------------------------------
045
046    /**
047     * Specify explicitly banned non-plugin repositories. This is a list of repository url patterns. Support wildcard
048     * "*".
049     * 
050     * @see {@link #setBannedRepositories(List)}
051     */
052    private List<String> bannedRepositories = Collections.emptyList();
053
054    /**
055     * Specify explicitly banned plugin repositories. This is a list of repository url patterns. Support wildcard "*".
056     * 
057     * @see {@link #setBannedPluginRepositories(List)}
058     */
059    private List<String> bannedPluginRepositories = Collections.emptyList();
060
061    /**
062     * Specify explicitly allowed non-plugin repositories, then all others repositories would be banned. This is a list
063     * of repository url patterns. Support wildcard "*".
064     * 
065     * @see {@link #setAllowedRepositories(List)}
066     */
067    private List<String> allowedRepositories = Collections.emptyList();
068
069    /**
070     * Specify explicitly allowed plugin repositories, then all others repositories would be banned. This is a list of
071     * repository url patterns. Support wildcard "*".
072     * 
073     * @see {@link #setAllowedPluginRepositories(List)}
074     */
075    private List<String> allowedPluginRepositories = Collections.emptyList();
076
077    // ----------------------------------------------------------------------
078    // Public methods
079    // ----------------------------------------------------------------------
080
081    @Override
082    public void execute( EnforcerRuleHelper helper )
083        throws EnforcerRuleException
084    {
085        MavenProject project;
086        try
087        {
088            project = (MavenProject) helper.evaluate( "${project}" );
089
090            List<ArtifactRepository> resultBannedRepos =
091                checkRepositories( project.getRemoteArtifactRepositories(), this.allowedRepositories,
092                                   this.bannedRepositories );
093
094            List<ArtifactRepository> resultBannedPluginRepos =
095                checkRepositories( project.getPluginArtifactRepositories(), this.allowedPluginRepositories,
096                                   this.bannedPluginRepositories );
097
098            String repoErrMsg = populateErrorMessage( resultBannedRepos, " " );
099            String pluginRepoErrMsg = populateErrorMessage( resultBannedPluginRepos, " plugin " );
100
101            String errMsg = repoErrMsg + pluginRepoErrMsg;
102
103            if ( errMsg != null && !StringUtils.isEmpty( errMsg.toString() ) )
104            {
105                throw new EnforcerRuleException( errMsg.toString() );
106            }
107
108        }
109        catch ( ExpressionEvaluationException e )
110        {
111            throw new EnforcerRuleException( e.getLocalizedMessage() );
112        }
113    }
114
115    // ----------------------------------------------------------------------
116    // Protected methods
117    // ----------------------------------------------------------------------
118
119    protected void setBannedRepositories( List<String> bannedRepositories )
120    {
121        this.bannedRepositories = bannedRepositories;
122    }
123
124    protected void setBannedPluginRepositories( List<String> bannedPluginRepositories )
125    {
126        this.bannedPluginRepositories = bannedPluginRepositories;
127    }
128
129    protected void setAllowedRepositories( List<String> allowedRepositories )
130    {
131        this.allowedRepositories = allowedRepositories;
132    }
133
134    protected void setAllowedPluginRepositories( List<String> allowedPluginRepositories )
135    {
136        this.allowedPluginRepositories = allowedPluginRepositories;
137    }
138
139    // ----------------------------------------------------------------------
140    // Private methods
141    // ----------------------------------------------------------------------
142
143    /**
144     * Check whether specified repositories have banned repositories.
145     * 
146     * @param repositories: candidate repositories.
147     * @param includes : 'include' patterns.
148     * @param excludes : 'exclude' patterns.
149     * @return Banned repositories.
150     */
151    private List<ArtifactRepository> checkRepositories( List<ArtifactRepository> repositories, List<String> includes,
152                                                        List<String> excludes )
153    {
154        List<ArtifactRepository> bannedRepos = new ArrayList<ArtifactRepository>();
155
156        for ( ArtifactRepository repo : repositories )
157        {
158            String url = repo.getUrl().trim();
159            if ( includes.size() > 0 && !match( url, includes ) )
160            {
161                bannedRepos.add( repo );
162                continue;
163            }
164
165            if ( excludes.size() > 0 && match( url, excludes ) )
166            {
167                bannedRepos.add( repo );
168            }
169
170        }
171
172        return bannedRepos;
173    }
174
175    private boolean match( String url, List<String> patterns )
176    {
177        for ( String pattern : patterns )
178        {
179            if ( this.match( url, pattern ) )
180            {
181                return true;
182            }
183        }
184
185        return false;
186    }
187
188    private boolean match( String text, String pattern )
189    {
190        return text.matches( pattern.replace( "?", ".?" ).replace( "*", ".*?" ) );
191    }
192
193    private String populateErrorMessage( List<ArtifactRepository> resultBannedRepos, String errorMessagePrefix )
194    {
195        StringBuffer errMsg = new StringBuffer( "" );
196        if ( !resultBannedRepos.isEmpty() )
197        {
198            errMsg.append( "Current maven session contains banned" + errorMessagePrefix
199                + "repository urls, please double check your pom or settings.xml:\n"
200                + getRepositoryUrlString( resultBannedRepos ) + "\n\n" );
201        }
202
203        return errMsg.toString();
204    }
205
206    private String getRepositoryUrlString( List<ArtifactRepository> resultBannedRepos )
207    {
208        StringBuffer urls = new StringBuffer( "" );
209        for ( ArtifactRepository repo : resultBannedRepos )
210        {
211            urls.append( repo.getId() + " - " + repo.getUrl() + "\n" );
212        }
213        return urls.toString();
214    }
215
216}