001    /**
002     * Copyright 2010-2012 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.apache.maven.project.ProjectBuildingException;
033    import org.codehaus.plexus.logging.AbstractLogEnabled;
034    import org.codehaus.plexus.logging.Logger;
035    
036    /**
037     * Default implementation of the {@link DependenciesTool}.
038     *
039     * @author tchemit <chemit@codelutin.com>
040     * @version $Id: DefaultDependenciesTool.java 14411 2011-08-10 22:09:34Z tchemit $
041     * @plexus.component role="org.codehaus.mojo.license.DependenciesTool" role-hint="default"
042     * @since 1.0
043     */
044    public class DefaultDependenciesTool extends AbstractLogEnabled implements DependenciesTool {
045    
046        public static final String INVALID_PATTERN_MESSAGE = "The pattern specified by expression <%s> seems to be invalid.";
047    
048        /**
049         * Project builder.
050         *
051         * @plexus.requirement
052         */
053        private MavenProjectBuilder mavenProjectBuilder;
054    
055        /**
056         * {@inheritDoc}
057         */
058        @Override
059        public SortedMap<String, MavenProject> loadProjectDependencies(MavenProject project,
060                MavenProjectDependenciesConfigurator configuration, ArtifactRepository localRepository,
061                List<ArtifactRepository> remoteRepositories, SortedMap<String, MavenProject> cache) {
062    
063            boolean haveNoIncludedGroups = StringUtils.isEmpty(configuration.getIncludedGroups());
064            boolean haveNoIncludedArtifacts = StringUtils.isEmpty(configuration.getIncludedArtifacts());
065    
066            boolean haveExcludedGroups = StringUtils.isNotEmpty(configuration.getExcludedGroups());
067            boolean haveExcludedArtifacts = StringUtils.isNotEmpty(configuration.getExcludedArtifacts());
068            boolean haveExclusions = haveExcludedGroups || haveExcludedArtifacts;
069    
070            Pattern includedGroupPattern = null;
071            Pattern includedArtifactPattern = null;
072            Pattern excludedGroupPattern = null;
073            Pattern excludedArtifactPattern = null;
074    
075            if (!haveNoIncludedGroups) {
076                includedGroupPattern = Pattern.compile(configuration.getIncludedGroups());
077            }
078            if (!haveNoIncludedArtifacts) {
079                includedArtifactPattern = Pattern.compile(configuration.getIncludedArtifacts());
080            }
081            if (haveExcludedGroups) {
082                excludedGroupPattern = Pattern.compile(configuration.getExcludedGroups());
083            }
084            if (haveExcludedArtifacts) {
085                excludedArtifactPattern = Pattern.compile(configuration.getExcludedArtifacts());
086            }
087    
088            Set<?> depArtifacts;
089    
090            if (configuration.isIncludeTransitiveDependencies()) {
091                // All project dependencies
092                depArtifacts = project.getArtifacts();
093            } else {
094                // Only direct project dependencies
095                depArtifacts = project.getDependencyArtifacts();
096            }
097    
098            List<String> includedScopes = configuration.getIncludedScopes();
099            List<String> excludeScopes = configuration.getExcludedScopes();
100    
101            boolean verbose = configuration.isVerbose();
102    
103            SortedMap<String, MavenProject> result = new TreeMap<String, MavenProject>();
104    
105            for (Object o : depArtifacts) {
106                Artifact artifact = (Artifact) o;
107    
108                String scope = artifact.getScope();
109                if (CollectionUtils.isNotEmpty(includedScopes) && !includedScopes.contains(scope)) {
110    
111                    // not in included scopes
112                    continue;
113                }
114                {
115                    if (excludeScopes.contains(scope)) {
116    
117                        // in excluded scopes
118                        continue;
119                    }
120                }
121    
122                Logger log = getLogger();
123    
124                String id = MojoHelper.getArtifactId(artifact);
125    
126                if (verbose) {
127                    log.info("detected artifact " + id);
128                }
129    
130                // Check if the project should be included
131                // If there is no specified artifacts and group to include, include all
132                boolean isToInclude = haveNoIncludedArtifacts && haveNoIncludedGroups
133                        || isIncludable(artifact, includedGroupPattern, includedArtifactPattern);
134    
135                // Check if the project should be excluded
136                boolean isToExclude = isToInclude && haveExclusions
137                        && isExcludable(artifact, excludedGroupPattern, excludedArtifactPattern);
138    
139                if (!isToInclude || isToExclude) {
140                    if (verbose) {
141                        log.info("skip artifact " + id);
142                    }
143                    continue;
144                }
145    
146                MavenProject depMavenProject = null;
147    
148                if (cache != null) {
149    
150                    // try to get project from cache
151                    depMavenProject = cache.get(id);
152                }
153    
154                if (depMavenProject != null) {
155                    if (verbose) {
156                        log.info("add dependency [" + id + "] (from cache)");
157                    }
158                } else {
159    
160                    // build project
161    
162                    try {
163                        depMavenProject = mavenProjectBuilder.buildFromRepository(artifact, remoteRepositories,
164                                localRepository, true);
165                    } catch (ProjectBuildingException e) {
166                        log.warn("Unable to obtain POM for artifact : " + artifact, e);
167                        continue;
168                    }
169    
170                    if (verbose) {
171                        log.info("add dependency [" + id + "]");
172                    }
173                    if (cache != null) {
174    
175                        // store it also in cache
176                        cache.put(id, depMavenProject);
177                    }
178                }
179    
180                // keep the project
181                result.put(id, depMavenProject);
182            }
183    
184            return result;
185        }
186    
187        protected boolean isIncludable(Artifact project, Pattern includedGroupPattern, Pattern includedArtifactPattern) {
188    
189            Logger log = getLogger();
190    
191            // check if the groupId of the project should be included
192            if (includedGroupPattern != null) {
193                // we have some defined license filters
194                try {
195                    Matcher matchGroupId = includedGroupPattern.matcher(project.getGroupId());
196                    if (matchGroupId.find()) {
197                        if (log.isDebugEnabled()) {
198                            log.debug("Include " + project.getGroupId());
199                        }
200                        return true;
201                    }
202                } catch (PatternSyntaxException e) {
203                    log.warn(String.format(INVALID_PATTERN_MESSAGE, includedGroupPattern.pattern()));
204                }
205            }
206    
207            // check if the artifactId of the project should be included
208            if (includedArtifactPattern != null) {
209                // we have some defined license filters
210                try {
211                    Matcher matchGroupId = includedArtifactPattern.matcher(project.getArtifactId());
212                    if (matchGroupId.find()) {
213                        if (log.isDebugEnabled()) {
214                            log.debug("Include " + project.getArtifactId());
215                        }
216                        return true;
217                    }
218                } catch (PatternSyntaxException e) {
219                    log.warn(String.format(INVALID_PATTERN_MESSAGE, includedArtifactPattern.pattern()));
220                }
221            }
222    
223            return false;
224        }
225    
226        protected boolean isExcludable(Artifact project, Pattern excludedGroupPattern, Pattern excludedArtifactPattern) {
227    
228            Logger log = getLogger();
229    
230            // check if the groupId of the project should be included
231            if (excludedGroupPattern != null) {
232                // we have some defined license filters
233                try {
234                    Matcher matchGroupId = excludedGroupPattern.matcher(project.getGroupId());
235                    if (matchGroupId.find()) {
236                        if (log.isDebugEnabled()) {
237                            log.debug("Exclude " + project.getGroupId());
238                        }
239                        return true;
240                    }
241                } catch (PatternSyntaxException e) {
242                    log.warn(String.format(INVALID_PATTERN_MESSAGE, excludedGroupPattern.pattern()));
243                }
244            }
245    
246            // check if the artifactId of the project should be included
247            if (excludedArtifactPattern != null) {
248                // we have some defined license filters
249                try {
250                    Matcher matchGroupId = excludedArtifactPattern.matcher(project.getArtifactId());
251                    if (matchGroupId.find()) {
252                        if (log.isDebugEnabled()) {
253                            log.debug("Exclude " + project.getArtifactId());
254                        }
255                        return true;
256                    }
257                } catch (PatternSyntaxException e) {
258                    log.warn(String.format(INVALID_PATTERN_MESSAGE, excludedArtifactPattern.pattern()));
259                }
260            }
261    
262            return false;
263        }
264    }