001    /*
002     *  Licensed under the Apache License, Version 2.0 (the "License");
003     *  you may not use this file except in compliance with the License.
004     *  You may obtain a copy of the License at
005     *
006     *      http://www.apache.org/licenses/LICENSE-2.0
007     *
008     *  Unless required by applicable law or agreed to in writing, software
009     *  distributed under the License is distributed on an "AS IS" BASIS,
010     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011     *  See the License for the specific language governing permissions and
012     *  limitations under the License.
013     */
014    /*
015     * This file has been modified by Chris Pheby in accordance with Section 4.2
016     * of the Apache Software License
017     */
018    package org.jadira.dependencynavigator.assembler;
019    
020    import java.util.ArrayList;
021    import java.util.Collections;
022    import java.util.HashMap;
023    import java.util.Iterator;
024    import java.util.List;
025    import java.util.Map;
026    
027    import org.apache.maven.artifact.Artifact;
028    import org.apache.maven.artifact.factory.ArtifactFactory;
029    import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
030    import org.apache.maven.artifact.versioning.VersionRange;
031    import org.apache.maven.model.Dependency;
032    import org.apache.maven.model.Model;
033    import org.apache.maven.model.Parent;
034    import org.apache.maven.project.ModelUtils;
035    import org.apache.maven.project.inheritance.ModelInheritanceAssembler;
036    import org.apache.maven.project.interpolation.ModelInterpolationException;
037    import org.apache.maven.project.interpolation.ModelInterpolator;
038    import org.jadira.dependencynavigator.implementations.Repository;
039    
040    /**
041     * Provides pom inheritance & properties support
042     */
043    public class Assembler {
044        
045        public static final String ROLE = "org.jadira.dependencynavigator.assembler.Assembler";
046    
047        private ModelInheritanceAssembler assembler;
048        private ModelInterpolator interpolator;
049        private ArtifactFactory artifactFactory;
050    
051        /**
052         * create a list of pom parents starting with the raw pom
053         */
054        private void lookupLineage(Model child, Repository repository, List<Model> lineage) {
055            if (child == null) {
056                return;
057            }
058            lineage.add(child);
059            Parent parentStub = child.getParent();
060            if (parentStub == null) {
061                return;
062            }
063            Model parent = repository.resolveFile(parentStub.getGroupId(), parentStub.getArtifactId(), parentStub.getVersion());
064            lookupLineage(parent, repository, lineage);
065        }
066    
067        /**
068         * work down the pom parents, merging the the parent into the child
069         */
070        private Model assemble(Model parent, List<Model> lineage, Repository repository) {
071            if (lineage.size() == 0) {
072                return parent;
073            }
074            Model child = (Model) lineage.remove(0);
075            assembler.assembleModelInheritance(child, parent);
076            return assemble(child, lineage, repository);
077        }
078    
079        private Model dependencyManagement(Model interpolated) throws AssemblerException {
080            try {
081                if (interpolated.getDependencyManagement() == null) {
082                    return interpolated;
083                }
084                Model managed = ModelUtils.cloneModel(interpolated);
085                Map<String, Dependency> managees = new HashMap<String, Dependency>();
086                for (Iterator<Dependency> iter = managed.getDependencies().iterator(); iter.hasNext();) {
087                    Dependency dependency = (Dependency) iter.next();
088                    managees.put(dependency.getGroupId() + ":" + dependency.getArtifactId(), dependency);
089                }
090                for (Iterator<Dependency> iter = interpolated.getDependencyManagement().getDependencies().iterator(); iter.hasNext();) {
091                    Dependency manager = (Dependency) iter.next();
092                    VersionRange versionRange = VersionRange.createFromVersionSpec(manager.getVersion());
093                    Artifact artifact = artifactFactory.createDependencyArtifact(manager.getGroupId(), manager.getArtifactId(), versionRange, manager.getType(), manager.getClassifier(), manager
094                            .getScope(), manager.isOptional());
095                    Dependency managee = (Dependency) managees.get(manager.getGroupId() + ":" + manager.getArtifactId());
096                    if (managee != null) {
097                        managee.setVersion(artifact.getVersion());
098                    }
099                }
100                return managed;
101            } catch (InvalidVersionSpecificationException e) {
102                throw new AssemblerException(e);
103            }
104        }
105    
106        public AssembledModel assemble(Model raw, Repository repository) throws AssemblerException {
107            try {
108                List<Model> lineage = new ArrayList<Model>();
109                lookupLineage(raw, repository, lineage);
110                Collections.reverse(lineage);
111                Model root = (Model) lineage.remove(0);
112                Model assembled = assemble(root, lineage, repository);
113                Model interpolated = interpolator.interpolate(assembled, new HashMap<String, Object>());
114                Model managed = dependencyManagement(interpolated);
115                return new AssembledModel(managed);
116            } catch (ModelInterpolationException e) {
117                throw new AssemblerException(e);
118            }
119        }
120    }