001    /*
002     * #%L
003     * License Maven Plugin
004     *
005     * $Id: DefaultDependenciesTool.java 14411 2011-08-10 22:09:34Z tchemit $
006     * $HeadURL: http://svn.codehaus.org/mojo/tags/license-maven-plugin-1.0/src/main/java/org/codehaus/mojo/license/DefaultDependenciesTool.java $
007     * %%
008     * Copyright (C) 2011 CodeLutin, Codehaus, Tony Chemit
009     * %%
010     * This program is free software: you can redistribute it and/or modify
011     * it under the terms of the GNU Lesser General Public License as
012     * published by the Free Software Foundation, either version 3 of the
013     * License, or (at your option) any later version.
014     *
015     * This program is distributed in the hope that it will be useful,
016     * but WITHOUT ANY WARRANTY; without even the implied warranty of
017     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
018     * GNU General Lesser Public License for more details.
019     *
020     * You should have received a copy of the GNU General Lesser Public
021     * License along with this program.  If not, see
022     * <http://www.gnu.org/licenses/lgpl-3.0.html>.
023     * #L%
024     */
025    package org.codehaus.mojo.license;
026    
027    import org.apache.commons.collections.CollectionUtils;
028    import org.apache.commons.lang.StringUtils;
029    import org.apache.maven.artifact.Artifact;
030    import org.apache.maven.artifact.repository.ArtifactRepository;
031    import org.apache.maven.project.MavenProject;
032    import org.apache.maven.project.MavenProjectBuilder;
033    import org.apache.maven.project.ProjectBuildingException;
034    import org.codehaus.plexus.logging.AbstractLogEnabled;
035    import org.codehaus.plexus.logging.Logger;
036    
037    import java.util.List;
038    import java.util.Set;
039    import java.util.SortedMap;
040    import java.util.TreeMap;
041    import java.util.regex.Matcher;
042    import java.util.regex.Pattern;
043    import java.util.regex.PatternSyntaxException;
044    
045    /**
046     * Default implementation of the {@link DependenciesTool}.
047     *
048     * @author tchemit <chemit@codelutin.com>
049     * @version $Id: DefaultDependenciesTool.java 14411 2011-08-10 22:09:34Z tchemit $
050     * @plexus.component role="org.codehaus.mojo.license.DependenciesTool" role-hint="default"
051     * @since 1.0
052     */
053    public class DefaultDependenciesTool
054        extends AbstractLogEnabled
055        implements DependenciesTool
056    {
057    
058        public static final String INVALID_PATTERN_MESSAGE =
059            "The pattern specified by expression <%s> seems to be invalid.";
060    
061        /**
062         * Project builder.
063         *
064         * @plexus.requirement
065         */
066        private MavenProjectBuilder mavenProjectBuilder;
067    
068        /**
069         * {@inheritDoc}
070         */
071        public SortedMap<String, MavenProject> loadProjectDependencies( MavenProject project,
072                                                                        MavenProjectDependenciesConfigurator configuration,
073                                                                        ArtifactRepository localRepository,
074                                                                        List<ArtifactRepository> remoteRepositories,
075                                                                        SortedMap<String, MavenProject> cache )
076        {
077    
078            boolean haveNoIncludedGroups = StringUtils.isEmpty( configuration.getIncludedGroups() );
079            boolean haveNoIncludedArtifacts = StringUtils.isEmpty( configuration.getIncludedArtifacts() );
080    
081            boolean haveExcludedGroups = StringUtils.isNotEmpty( configuration.getExcludedGroups() );
082            boolean haveExcludedArtifacts = StringUtils.isNotEmpty( configuration.getExcludedArtifacts() );
083            boolean haveExclusions = haveExcludedGroups || haveExcludedArtifacts;
084    
085            Pattern includedGroupPattern = null;
086            Pattern includedArtifactPattern = null;
087            Pattern excludedGroupPattern = null;
088            Pattern excludedArtifactPattern = null;
089    
090            if ( !haveNoIncludedGroups )
091            {
092                includedGroupPattern = Pattern.compile( configuration.getIncludedGroups() );
093            }
094            if ( !haveNoIncludedArtifacts )
095            {
096                includedArtifactPattern = Pattern.compile( configuration.getIncludedArtifacts() );
097            }
098            if ( haveExcludedGroups )
099            {
100                excludedGroupPattern = Pattern.compile( configuration.getExcludedGroups() );
101            }
102            if ( haveExcludedArtifacts )
103            {
104                excludedArtifactPattern = Pattern.compile( configuration.getExcludedArtifacts() );
105            }
106    
107            Set<?> depArtifacts;
108    
109            if ( configuration.isIncludeTransitiveDependencies() )
110            {
111                // All project dependencies
112                depArtifacts = project.getArtifacts();
113            }
114            else
115            {
116                // Only direct project dependencies
117                depArtifacts = project.getDependencyArtifacts();
118            }
119    
120            List<String> includedScopes = configuration.getIncludedScopes();
121            List<String> excludeScopes = configuration.getExcludedScopes();
122    
123            boolean verbose = configuration.isVerbose();
124    
125            SortedMap<String, MavenProject> result = new TreeMap<String, MavenProject>();
126    
127            for ( Object o : depArtifacts )
128            {
129                Artifact artifact = (Artifact) o;
130    
131                String scope = artifact.getScope();
132                if ( CollectionUtils.isNotEmpty( includedScopes ) && !includedScopes.contains( scope ) )
133                {
134    
135                    // not in included scopes
136                    continue;
137                }
138                {
139                    if ( excludeScopes.contains( scope ) )
140                    {
141    
142                        // in exluced scopes 
143                        continue;
144                    }
145                }
146    
147                Logger log = getLogger();
148    
149                String id = MojoHelper.getArtifactId( artifact );
150    
151                if ( verbose )
152                {
153                    log.info( "detected artifact " + id );
154                }
155    
156                // Check if the project should be included
157                // If there is no specified artifacts and group to include, include all
158                boolean isToInclude = haveNoIncludedArtifacts && haveNoIncludedGroups ||
159                    isIncludable( artifact, includedGroupPattern, includedArtifactPattern );
160    
161                // Check if the project should be excluded
162                boolean isToExclude = isToInclude && haveExclusions &&
163                    isExcludable( artifact, excludedGroupPattern, excludedArtifactPattern );
164    
165                if ( !isToInclude || isToExclude )
166                {
167                    if ( verbose )
168                    {
169                        log.info( "skip artifact " + id );
170                    }
171                    continue;
172                }
173    
174                MavenProject depMavenProject = null;
175    
176                if ( cache != null )
177                {
178    
179                    // try to get project from cache
180                    depMavenProject = cache.get( id );
181                }
182    
183                if ( depMavenProject != null )
184                {
185                    if ( verbose )
186                    {
187                        log.info( "add dependency [" + id + "] (from cache)" );
188                    }
189                }
190                else
191                {
192    
193                    // build project
194    
195                    try
196                    {
197                        depMavenProject =
198                            mavenProjectBuilder.buildFromRepository( artifact, remoteRepositories, localRepository, true );
199                    }
200                    catch ( ProjectBuildingException e )
201                    {
202                        log.warn( "Unable to obtain POM for artifact : " + artifact, e );
203                        continue;
204                    }
205    
206                    if ( verbose )
207                    {
208                        log.info( "add dependency [" + id + "]" );
209                    }
210                    if ( cache != null )
211                    {
212    
213                        // store it also in cache
214                        cache.put( id, depMavenProject );
215                    }
216                }
217    
218                // keep the project
219                result.put( id, depMavenProject );
220            }
221    
222            return result;
223        }
224    
225        protected boolean isIncludable( Artifact project, Pattern includedGroupPattern, Pattern includedArtifactPattern )
226        {
227    
228            Logger log = getLogger();
229    
230            // check if the groupId of the project should be included
231            if ( includedGroupPattern != null )
232            {
233                // we have some defined license filters
234                try
235                {
236                    Matcher matchGroupId = includedGroupPattern.matcher( project.getGroupId() );
237                    if ( matchGroupId.find() )
238                    {
239                        if ( log.isDebugEnabled() )
240                        {
241                            log.debug( "Include " + project.getGroupId() );
242                        }
243                        return true;
244                    }
245                }
246                catch ( PatternSyntaxException e )
247                {
248                    log.warn( String.format( INVALID_PATTERN_MESSAGE, includedGroupPattern.pattern() ) );
249                }
250            }
251    
252            // check if the artifactId of the project should be included
253            if ( includedArtifactPattern != null )
254            {
255                // we have some defined license filters
256                try
257                {
258                    Matcher matchGroupId = includedArtifactPattern.matcher( project.getArtifactId() );
259                    if ( matchGroupId.find() )
260                    {
261                        if ( log.isDebugEnabled() )
262                        {
263                            log.debug( "Include " + project.getArtifactId() );
264                        }
265                        return true;
266                    }
267                }
268                catch ( PatternSyntaxException e )
269                {
270                    log.warn( String.format( INVALID_PATTERN_MESSAGE, includedArtifactPattern.pattern() ) );
271                }
272            }
273    
274            return false;
275        }
276    
277        protected boolean isExcludable( Artifact project, Pattern excludedGroupPattern, Pattern excludedArtifactPattern )
278        {
279    
280            Logger log = getLogger();
281    
282            // check if the groupId of the project should be included
283            if ( excludedGroupPattern != null )
284            {
285                // we have some defined license filters
286                try
287                {
288                    Matcher matchGroupId = excludedGroupPattern.matcher( project.getGroupId() );
289                    if ( matchGroupId.find() )
290                    {
291                        if ( log.isDebugEnabled() )
292                        {
293                            log.debug( "Exclude " + project.getGroupId() );
294                        }
295                        return true;
296                    }
297                }
298                catch ( PatternSyntaxException e )
299                {
300                    log.warn( String.format( INVALID_PATTERN_MESSAGE, excludedGroupPattern.pattern() ) );
301                }
302            }
303    
304            // check if the artifactId of the project should be included
305            if ( excludedArtifactPattern != null )
306            {
307                // we have some defined license filters
308                try
309                {
310                    Matcher matchGroupId = excludedArtifactPattern.matcher( project.getArtifactId() );
311                    if ( matchGroupId.find() )
312                    {
313                        if ( log.isDebugEnabled() )
314                        {
315                            log.debug( "Exclude " + project.getArtifactId() );
316                        }
317                        return true;
318                    }
319                }
320                catch ( PatternSyntaxException e )
321                {
322                    log.warn( String.format( INVALID_PATTERN_MESSAGE, excludedArtifactPattern.pattern() ) );
323                }
324            }
325    
326            return false;
327        }
328    }