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 1496229 2013-06-24 21:43:56Z rfscholte $
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     * @deprecated the visibility will be reduced to private with the next major version
052     * @see {@link #setOnlyWhenRelease(boolean)}
053     * @see {@link #isOnlyWhenRelease()}
054
055     */
056    public boolean onlyWhenRelease = false;
057
058    /**
059     * Allows this rule to fail when the parent is defined as a snapshot.
060     *
061     * @parameter
062     * 
063     * @deprecated the visibility will be reduced to private with the next major version
064     * @see {@link #setFailWhenParentIsSnapshot(boolean)}
065     * @see {@link #isFailWhenParentIsSnapshot()}
066     */
067    public boolean failWhenParentIsSnapshot = true;
068
069    /**
070     * Dependencies to ignore when checking for release versions.  For example, inter-module dependencies 
071     * can be excluded from the check and therefore allowed to contain snapshot versions.
072     * 
073     * @deprecated the visibility will be reduced to private with the next major version
074     * @see {@link #setExcludes(List)}
075     * @see {@link #getExcludes()}
076     */
077    public List<String> excludes = null;
078
079    /**
080     * Dependencies to include when checking for release versions.  If any of the included dependencies
081     * have snapshot versions, the rule will fail.
082     * 
083     * @deprecated the visibility will be reduced to private with the next major version
084     * @see {@link #setIncludes(List)}
085     * @see {@link #getIncludes()}
086     */
087    public List<String> includes = null;
088
089    /**
090     * Override parent to allow optional ignore of this rule.
091     * 
092     * @param helper the enforcerRuleHelper
093     * @throws EnforcerRuleException when an exception occurs
094     */
095    public void execute( EnforcerRuleHelper helper )
096        throws EnforcerRuleException
097    {
098        boolean callSuper;
099        MavenProject project = null;
100        if ( onlyWhenRelease )
101        {
102            // get the project
103            project = getProject( helper );
104
105            // only call super if this project is a release
106            callSuper = !project.getArtifact().isSnapshot();
107        }
108        else
109        {
110            callSuper = true;
111        }
112        if ( callSuper )
113        {
114            super.execute( helper );
115            if ( failWhenParentIsSnapshot )
116            {
117                if ( project == null )
118                {
119                    project = getProject( helper );
120                }
121                Artifact parentArtifact = project.getParentArtifact();
122                if ( parentArtifact != null && parentArtifact.isSnapshot() )
123                {
124                    throw new EnforcerRuleException( "Parent Cannot be a snapshot: " + parentArtifact.getId() );
125                }
126            }
127        }
128    }
129
130    /**
131     * @param helper
132     * @return
133     * @throws EnforcerRuleException
134     */
135    private MavenProject getProject( EnforcerRuleHelper helper )
136        throws EnforcerRuleException
137    {
138        try
139        {
140            return (MavenProject) helper.evaluate( "${project}" );
141        }
142        catch ( ExpressionEvaluationException eee )
143        {
144            throw new EnforcerRuleException( "Unable to retrieve the MavenProject: ", eee );
145        }
146    }
147
148
149    /**
150     * {@inheritDoc}
151     */
152    protected Set<Artifact> checkDependencies( Set<Artifact> dependencies, Log log )
153        throws EnforcerRuleException
154    {
155        Set<Artifact> foundSnapshots = new HashSet<Artifact>();
156
157        Set<Artifact> filteredDependencies = filterArtifacts( dependencies );
158        
159        for ( Artifact artifact : filteredDependencies )
160        {
161            if ( artifact.isSnapshot() )
162            {
163                foundSnapshots.add( artifact );
164            }
165        }
166
167        return foundSnapshots;
168    }
169    
170    /*
171     * Filter the dependency artifacts according to the includes and excludes
172     * If includes and excludes are both null, the original set is returned.
173     * 
174     * @param dependencies the list of dependencies to filter
175     * @return the resulting set of dependencies
176     */
177    public Set<Artifact> filterArtifacts( Set<Artifact> dependencies )
178    {
179        if ( includes == null && excludes == null )
180        {
181            return dependencies;
182        }
183        
184        AndArtifactFilter filter = new AndArtifactFilter( );
185        if ( includes != null )
186        {
187            filter.add( new StrictPatternIncludesArtifactFilter( includes ) );
188        }
189        if ( excludes != null )
190        {
191            filter.add( new StrictPatternExcludesArtifactFilter( excludes ) );
192        }
193        
194        Set<Artifact> result = new HashSet<Artifact>();
195        for ( Artifact artifact : dependencies )
196        {
197            if ( filter.include( artifact ) )
198            {
199                result.add( artifact );
200            }
201        }
202        return result;
203    }
204
205    public final boolean isOnlyWhenRelease()
206    {
207        return onlyWhenRelease;
208    }
209
210    public final void setOnlyWhenRelease( boolean onlyWhenRelease )
211    {
212        this.onlyWhenRelease = onlyWhenRelease;
213    }
214
215    public final boolean isFailWhenParentIsSnapshot()
216    {
217        return failWhenParentIsSnapshot;
218    }
219
220    public final void setFailWhenParentIsSnapshot( boolean failWhenParentIsSnapshot )
221    {
222        this.failWhenParentIsSnapshot = failWhenParentIsSnapshot;
223    }
224    
225    public final void setExcludes( List<String> excludes )
226    {
227        this.excludes = excludes;
228    }
229    
230    public final List<String> getExcludes()
231    {
232        return excludes;
233    }
234    
235    public void setIncludes( List<String> includes )
236    {
237        this.includes = includes;
238    }
239    
240    public List<String> getIncludes()
241    {
242        return includes;
243    }
244}