001    /**
002     * Copyright 2010-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.codehaus.mojo.license;
017    
018    import java.util.List;
019    import java.util.Set;
020    import java.util.SortedMap;
021    import java.util.TreeMap;
022    import java.util.regex.Matcher;
023    import java.util.regex.Pattern;
024    import java.util.regex.PatternSyntaxException;
025    
026    import org.apache.commons.collections.CollectionUtils;
027    import org.apache.commons.lang.StringUtils;
028    import org.apache.maven.artifact.Artifact;
029    import org.apache.maven.artifact.repository.ArtifactRepository;
030    import org.apache.maven.project.MavenProject;
031    import org.apache.maven.project.MavenProjectBuilder;
032    import org.codehaus.plexus.logging.AbstractLogEnabled;
033    import org.codehaus.plexus.logging.Logger;
034    
035    /**
036     * Default implementation of the {@link DependenciesTool}.
037     * 
038     * @author tchemit <chemit@codelutin.com>
039     * @version $Id: DefaultDependenciesTool.java 14411 2011-08-10 22:09:34Z tchemit $
040     * @plexus.component role="org.codehaus.mojo.license.DependenciesTool" role-hint="default"
041     * @since 1.0
042     */
043    public class DefaultDependenciesTool extends AbstractLogEnabled implements DependenciesTool {
044    
045            public static final String INVALID_PATTERN_MESSAGE = "The pattern specified by expression <%s> seems to be invalid.";
046    
047            /**
048             * Project builder.
049             * 
050             * @plexus.requirement
051             */
052            private MavenProjectBuilder mavenProjectBuilder;
053    
054            /**
055             * {@inheritDoc}
056             */
057            @Override
058            public SortedMap<String, MavenProject> loadProjectDependencies(MavenProject project, MavenProjectDependenciesConfigurator configuration, ArtifactRepository localRepository,
059                            List<ArtifactRepository> remoteRepositories, SortedMap<String, MavenProject> cache) {
060    
061                    boolean haveNoIncludedGroups = StringUtils.isEmpty(configuration.getIncludedGroups());
062                    boolean haveNoIncludedArtifacts = StringUtils.isEmpty(configuration.getIncludedArtifacts());
063    
064                    boolean haveExcludedGroups = StringUtils.isNotEmpty(configuration.getExcludedGroups());
065                    boolean haveExcludedArtifacts = StringUtils.isNotEmpty(configuration.getExcludedArtifacts());
066                    boolean haveExclusions = haveExcludedGroups || haveExcludedArtifacts;
067    
068                    Pattern includedGroupPattern = null;
069                    Pattern includedArtifactPattern = null;
070                    Pattern excludedGroupPattern = null;
071                    Pattern excludedArtifactPattern = null;
072    
073                    if (!haveNoIncludedGroups) {
074                            includedGroupPattern = Pattern.compile(configuration.getIncludedGroups());
075                    }
076                    if (!haveNoIncludedArtifacts) {
077                            includedArtifactPattern = Pattern.compile(configuration.getIncludedArtifacts());
078                    }
079                    if (haveExcludedGroups) {
080                            excludedGroupPattern = Pattern.compile(configuration.getExcludedGroups());
081                    }
082                    if (haveExcludedArtifacts) {
083                            excludedArtifactPattern = Pattern.compile(configuration.getExcludedArtifacts());
084                    }
085    
086                    Set<?> depArtifacts;
087    
088                    if (configuration.isIncludeTransitiveDependencies()) {
089                            // All project dependencies
090                            depArtifacts = project.getArtifacts();
091                    } else {
092                            // Only direct project dependencies
093                            depArtifacts = project.getDependencyArtifacts();
094                    }
095    
096                    List<String> includedScopes = configuration.getIncludedScopes();
097                    List<String> excludeScopes = configuration.getExcludedScopes();
098    
099                    boolean verbose = configuration.isVerbose();
100    
101                    SortedMap<String, MavenProject> result = new TreeMap<String, MavenProject>();
102    
103                    for (Object o : depArtifacts) {
104                            Artifact artifact = (Artifact) o;
105    
106                            String scope = artifact.getScope();
107                            if (CollectionUtils.isNotEmpty(includedScopes) && !includedScopes.contains(scope)) {
108                                    // not in included scopes
109                                    continue;
110                            }
111                            if (excludeScopes.contains(scope)) {
112                                    // in excluded scopes
113                                    continue;
114                            }
115    
116                            Logger log = getLogger();
117    
118                            String id = MojoHelper.getArtifactId(artifact);
119    
120                            if (verbose) {
121                                    log.info("detected artifact " + id);
122                            }
123    
124                            // Check if the project should be included
125                            // If there is no specified artifacts and group to include, include all
126                            boolean isToInclude = haveNoIncludedArtifacts && haveNoIncludedGroups || isIncludable(artifact, includedGroupPattern, includedArtifactPattern);
127    
128                            // Check if the project should be excluded
129                            boolean isToExclude = isToInclude && haveExclusions && isExcludable(artifact, excludedGroupPattern, excludedArtifactPattern);
130    
131                            if (!isToInclude || isToExclude) {
132                                    if (verbose) {
133                                            log.info("skip artifact " + id);
134                                    }
135                                    continue;
136                            }
137    
138                            MavenProject depMavenProject = null;
139    
140                            if (cache != null) {
141    
142                                    // try to get project from cache
143                                    depMavenProject = cache.get(id);
144                            }
145    
146                            if (depMavenProject != null) {
147                                    if (verbose) {
148                                            log.info("add dependency [" + id + "] (from cache)");
149                                    }
150                            } else {
151                                    // build project
152                                    try {
153                                            depMavenProject = mavenProjectBuilder.buildFromRepository(artifact, remoteRepositories, localRepository, true);
154                                    } catch (Exception e) {
155                                            log.warn("Unable to obtain POM for artifact : " + artifact, e);
156                                            continue;
157                                    }
158    
159                                    if (verbose) {
160                                            log.info("add dependency [" + id + "]");
161                                    }
162                                    if (cache != null) {
163                                            // store it also in cache
164                                            cache.put(id, depMavenProject);
165                                    }
166                            }
167    
168                            // keep the project
169                            result.put(id, depMavenProject);
170                    }
171    
172                    return result;
173            }
174    
175            protected boolean isIncludable(Artifact project, Pattern includedGroupPattern, Pattern includedArtifactPattern) {
176    
177                    Logger log = getLogger();
178    
179                    // check if the groupId of the project should be included
180                    if (includedGroupPattern != null) {
181                            // we have some defined license filters
182                            try {
183                                    Matcher matchGroupId = includedGroupPattern.matcher(project.getGroupId());
184                                    if (matchGroupId.find()) {
185                                            if (log.isDebugEnabled()) {
186                                                    log.debug("Include " + project.getGroupId());
187                                            }
188                                            return true;
189                                    }
190                            } catch (PatternSyntaxException e) {
191                                    log.warn(String.format(INVALID_PATTERN_MESSAGE, includedGroupPattern.pattern()));
192                            }
193                    }
194    
195                    // check if the artifactId of the project should be included
196                    if (includedArtifactPattern != null) {
197                            // we have some defined license filters
198                            try {
199                                    Matcher matchGroupId = includedArtifactPattern.matcher(project.getArtifactId());
200                                    if (matchGroupId.find()) {
201                                            if (log.isDebugEnabled()) {
202                                                    log.debug("Include " + project.getArtifactId());
203                                            }
204                                            return true;
205                                    }
206                            } catch (PatternSyntaxException e) {
207                                    log.warn(String.format(INVALID_PATTERN_MESSAGE, includedArtifactPattern.pattern()));
208                            }
209                    }
210    
211                    return false;
212            }
213    
214            protected boolean isExcludable(Artifact project, Pattern excludedGroupPattern, Pattern excludedArtifactPattern) {
215    
216                    Logger log = getLogger();
217    
218                    // check if the groupId of the project should be included
219                    if (excludedGroupPattern != null) {
220                            // we have some defined license filters
221                            try {
222                                    Matcher matchGroupId = excludedGroupPattern.matcher(project.getGroupId());
223                                    if (matchGroupId.find()) {
224                                            if (log.isDebugEnabled()) {
225                                                    log.debug("Exclude " + project.getGroupId());
226                                            }
227                                            return true;
228                                    }
229                            } catch (PatternSyntaxException e) {
230                                    log.warn(String.format(INVALID_PATTERN_MESSAGE, excludedGroupPattern.pattern()));
231                            }
232                    }
233    
234                    // check if the artifactId of the project should be included
235                    if (excludedArtifactPattern != null) {
236                            // we have some defined license filters
237                            try {
238                                    Matcher matchGroupId = excludedArtifactPattern.matcher(project.getArtifactId());
239                                    if (matchGroupId.find()) {
240                                            if (log.isDebugEnabled()) {
241                                                    log.debug("Exclude " + project.getArtifactId());
242                                            }
243                                            return true;
244                                    }
245                            } catch (PatternSyntaxException e) {
246                                    log.warn(String.format(INVALID_PATTERN_MESSAGE, excludedArtifactPattern.pattern()));
247                            }
248                    }
249    
250                    return false;
251            }
252    }