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.HashSet;
023import java.util.List;
024import java.util.Set;
025
026import org.apache.maven.artifact.Artifact;
027import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
028import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
029import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
030import org.apache.maven.plugin.logging.Log;
031import org.apache.maven.project.MavenProject;
032import org.apache.maven.shared.artifact.filter.StrictPatternExcludesArtifactFilter;
033import org.apache.maven.shared.artifact.filter.StrictPatternIncludesArtifactFilter;
034import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
035
036/**
037 * This rule checks that no snapshots are included.
038 *
039 * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
040 * @version $Id: RequireReleaseDeps.java 1697215 2015-08-23 16:27:17Z khmarbaise $
041 */
042public class RequireReleaseDeps
043    extends AbstractBanDependencies
044{
045
046    /**
047     * Allows this rule to execute only when this project is a release.
048     *
049     * @parameter
050     * 
051     * @see {@link #setOnlyWhenRelease(boolean)}
052     * @see {@link #isOnlyWhenRelease()}
053
054     */
055    private boolean onlyWhenRelease = false;
056
057    /**
058     * Allows this rule to fail when the parent is defined as a snapshot.
059     *
060     * @parameter
061     * 
062     * @see {@link #setFailWhenParentIsSnapshot(boolean)}
063     * @see {@link #isFailWhenParentIsSnapshot()}
064     */
065    private boolean failWhenParentIsSnapshot = true;
066
067    /**
068     * Dependencies to ignore when checking for release versions.  For example, inter-module dependencies 
069     * can be excluded from the check and therefore allowed to contain snapshot versions.
070     * 
071     * @see {@link #setExcludes(List)}
072     * @see {@link #getExcludes()}
073     */
074    private List<String> excludes = null;
075
076    /**
077     * Dependencies to include when checking for release versions.  If any of the included dependencies
078     * have snapshot versions, the rule will fail.
079     * 
080     * @see {@link #setIncludes(List)}
081     * @see {@link #getIncludes()}
082     */
083    private List<String> includes = null;
084
085    /**
086     * Override parent to allow optional ignore of this rule.
087     * 
088     * @param helper the enforcerRuleHelper
089     * @throws EnforcerRuleException when an exception occurs
090     */
091    public void execute( EnforcerRuleHelper helper )
092        throws EnforcerRuleException
093    {
094        boolean callSuper;
095        MavenProject project = null;
096        if ( onlyWhenRelease )
097        {
098            // get the project
099            project = getProject( helper );
100
101            // only call super if this project is a release
102            callSuper = !project.getArtifact().isSnapshot();
103        }
104        else
105        {
106            callSuper = true;
107        }
108        if ( callSuper )
109        {
110            super.execute( helper );
111            if ( failWhenParentIsSnapshot )
112            {
113                if ( project == null )
114                {
115                    project = getProject( helper );
116                }
117                Artifact parentArtifact = project.getParentArtifact();
118                if ( parentArtifact != null && parentArtifact.isSnapshot() )
119                {
120                    throw new EnforcerRuleException( "Parent Cannot be a snapshot: " + parentArtifact.getId() );
121                }
122            }
123        }
124    }
125
126    /**
127     * @param helper
128     * @return The evaluated {@link MavenProject}.
129     * @throws EnforcerRuleException
130     */
131    private MavenProject getProject( EnforcerRuleHelper helper )
132        throws EnforcerRuleException
133    {
134        try
135        {
136            return (MavenProject) helper.evaluate( "${project}" );
137        }
138        catch ( ExpressionEvaluationException eee )
139        {
140            throw new EnforcerRuleException( "Unable to retrieve the MavenProject: ", eee );
141        }
142    }
143
144
145    /**
146     * {@inheritDoc}
147     */
148    protected Set<Artifact> checkDependencies( Set<Artifact> dependencies, Log log )
149        throws EnforcerRuleException
150    {
151        Set<Artifact> foundSnapshots = new HashSet<Artifact>();
152
153        Set<Artifact> filteredDependencies = filterArtifacts( dependencies );
154        
155        for ( Artifact artifact : filteredDependencies )
156        {
157            if ( artifact.isSnapshot() )
158            {
159                foundSnapshots.add( artifact );
160            }
161        }
162
163        return foundSnapshots;
164    }
165    
166    /*
167     * Filter the dependency artifacts according to the includes and excludes
168     * If includes and excludes are both null, the original set is returned.
169     * 
170     * @param dependencies the list of dependencies to filter
171     * @return the resulting set of dependencies
172     */
173    public Set<Artifact> filterArtifacts( Set<Artifact> dependencies )
174    {
175        if ( includes == null && excludes == null )
176        {
177            return dependencies;
178        }
179        
180        AndArtifactFilter filter = new AndArtifactFilter( );
181        if ( includes != null )
182        {
183            filter.add( new StrictPatternIncludesArtifactFilter( includes ) );
184        }
185        if ( excludes != null )
186        {
187            filter.add( new StrictPatternExcludesArtifactFilter( excludes ) );
188        }
189        
190        Set<Artifact> result = new HashSet<Artifact>();
191        for ( Artifact artifact : dependencies )
192        {
193            if ( filter.include( artifact ) )
194            {
195                result.add( artifact );
196            }
197        }
198        return result;
199    }
200
201    public final boolean isOnlyWhenRelease()
202    {
203        return onlyWhenRelease;
204    }
205
206    public final void setOnlyWhenRelease( boolean onlyWhenRelease )
207    {
208        this.onlyWhenRelease = onlyWhenRelease;
209    }
210
211    public final boolean isFailWhenParentIsSnapshot()
212    {
213        return failWhenParentIsSnapshot;
214    }
215
216    public final void setFailWhenParentIsSnapshot( boolean failWhenParentIsSnapshot )
217    {
218        this.failWhenParentIsSnapshot = failWhenParentIsSnapshot;
219    }
220    
221    public final void setExcludes( List<String> excludes )
222    {
223        this.excludes = excludes;
224    }
225    
226    public final List<String> getExcludes()
227    {
228        return excludes;
229    }
230    
231    public void setIncludes( List<String> includes )
232    {
233        this.includes = includes;
234    }
235    
236    public List<String> getIncludes()
237    {
238        return includes;
239    }
240}