All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.plugin.DependencyUtil Maven / Gradle / Ivy

There is a newer version: 2.4.1
Show newest version
package org.nuiton.plugin;

/*
 * #%L
 * Helper Maven Plugin :: API
 * $Id: DependencyUtil.java 876 2012-11-11 08:14:19Z tchemit $
 * $HeadURL: http://svn.nuiton.org/svn/maven-helper-plugin/tags/maven-helper-plugin-2.1/helper-maven-plugin-api/src/main/java/org/nuiton/plugin/DependencyUtil.java $
 * %%
 * Copyright (C) 2009 - 2012 Codelutin, Tony Chemit
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.shared.dependency.tree.DependencyNode;

import java.util.*;

/**
 * Une classe de methodes utiles sur les dependences entre artifacts.
 *
 * @author tchemit 
 * @since 0.5
 */
public class DependencyUtil {

    /** to use log facility, just put in your code: log.info(\"...\"); */
    private static final Log log = LogFactory.getLog(DependencyUtil.class);

    public static void sortArtifacts(DependencyNode rootNode,
                                     List artifacts,
                                     boolean verbose) {

        if (artifacts.size() < 2) {
            return;
        }

        Map dico =
                new HashMap(artifacts.size());

        for (Artifact a : artifacts) {
            ArtifactDependencyEntry entry = new ArtifactDependencyEntry(a);
            dico.put(entry.artifactKey, entry);
        }

        // contient les artifacts non encore fixes
        Set universe = new HashSet(dico.keySet());

        // recupere les noeuds pour chaque artifact en une seule passe

        setNodes(rootNode, dico, universe, verbose);

        // contient les artifacts resouds dans l'ordre de dependances
        List parsed = new ArrayList();

        // premiere passe pour recuperer l'ensemble des dependances
        for (ArtifactDependencyEntry entry : dico.values()) {
            List dependencies = getDependencies(rootNode,
                                                        entry,
                                                        universe,
                                                        verbose
            );
            entry.depIds = dependencies;
        }

        int level = 0;
        do {
            if (verbose) {
                log.info("run into level " + level++);
            }
            // on parcourt les artifacts pour detecter les nouveau
            // artifacts fixes
            List levelFixed = new ArrayList();

            for (String key : universe) {
                ArtifactDependencyEntry entry = dico.get(key);
                // cet artifact n'est pas encore fixe
                if (entry.depIds.isEmpty()) {
                    // plus de dependance pour cet artifact
                    levelFixed.add(key);
                    if (verbose) {
                        log.info("fixed artifact " + key);
                    }
                }
            }

            if (levelFixed.isEmpty()) {
                // aucune modification, c'est un cycle!
                throw new IllegalStateException(
                        "cycle detecte ! entre les artifacts " + universe);
            }

            // on met a jour les listes
            universe.removeAll(levelFixed);
            parsed.addAll(levelFixed);

            if (universe.isEmpty()) {
                // tout a ete resolu, plus rien a faire
                break;
            }

            // on supprime les dependances fixees a ce niveau
            for (String key : universe) {
                ArtifactDependencyEntry entry = dico.get(key);
                entry.depIds.removeAll(levelFixed);
            }

            levelFixed.clear();
        } while (true);

        artifacts.clear();
        for (String key : parsed) {
            artifacts.add(dico.get(key).artifact);
        }

    }

    protected static String getArtifactId(Artifact artifact) {
        return artifact.getArtifactId() + ":" + artifact.getGroupId();
    }

    protected static List getDependencies(
            DependencyNode rootNode,
            ArtifactDependencyEntry entry,
            Set universe,
            boolean verbose) {

        List order = new ArrayList();
        Set exclude = new HashSet();

        if (verbose) {
            log.info("start [" + entry.artifactKey + "]");
        }
        DependencyNode node = entry.node;

        getDependencies(rootNode,
                        node,
                        entry.artifactKey,
                        universe,
                        verbose,
                        order,
                        exclude
        );

        return order;
    }

    private static void getDependencies(DependencyNode rootNode,
                                        DependencyNode node,
                                        String artifactKey,
                                        Set universe,
                                        boolean verbose,
                                        List order,
                                        Set exclude) {

        for (Iterator itr = node.preorderIterator(); itr.hasNext();) {
            DependencyNode d = (DependencyNode) itr.next();
            Artifact artifact = d.getArtifact();
            String key = getArtifactId(artifact);
            if (artifactKey.equals(key)) {
                // artifact du noeud en parametre, rien a faire
                continue;
            }
            if (order.contains(key) || exclude.contains(key)) {
                // artifact deja rencontree
                continue;
            }

            if (d.getState() != DependencyNode.INCLUDED) {
                // on doit recuperer le noeud complete
                if (log.isDebugEnabled()) {
                    log.debug("!!! doit recuperer le noeud complet pour " +
                              d.getArtifact());
                }
                DependencyNode node1 = getNode(rootNode, key, verbose);
                getDependencies(rootNode,
                                node1,
                                artifactKey,
                                universe,
                                verbose,
                                order,
                                exclude
                );
            }

            if (log.isDebugEnabled()) {
                log.debug("[" + artifactKey + "] ???????  [" + key + "]");
            }

            if (universe.contains(key)) {
                // artifact a retenir
                if (verbose) {
                    log.info(" <<  [" + d.getArtifact() + "]");
                }
                order.add(key);
                continue;
            }

            // cet artifact peut etre marque comme a ne plus etre scanne
            exclude.add(key);
        }

    }

    protected static void setNodes(DependencyNode rootNode,
                                   Map dico,
                                   Set universe,
                                   boolean verbose) {

        for (Iterator itr = rootNode.preorderIterator(); itr.hasNext();) {
            DependencyNode d = (DependencyNode) itr.next();
            Artifact artifact = d.getArtifact();
            String key = getArtifactId(artifact);
            if (log.isDebugEnabled()) {
                log.debug("key : " + key);
            }
            if (universe.contains(key) &&
                d.getState() == DependencyNode.INCLUDED) {
                ArtifactDependencyEntry entry = dico.get(key);
                entry.node = d;
//                if (d == null) {
//                    // ce cas ne devrait jamais arrive
//                    throw new IllegalStateException(
//                            "on a pas trouve le node pour l'artifact " +
//                            artifact);
//                }
                if (log.isDebugEnabled()) {
                    log.debug("detected node : " + d);
                }
            }
        }
    }

    protected static DependencyNode getNode(DependencyNode rootNode,
                                            String requiredKey,
                                            boolean verbose) {

        for (Iterator itr = rootNode.preorderIterator(); itr.hasNext();) {
            DependencyNode d = (DependencyNode) itr.next();
            Artifact artifact = d.getArtifact();
            String key = getArtifactId(artifact);
            if (log.isDebugEnabled()) {
                log.debug("key : " + key);
            }
            if (requiredKey.equals(key) &&
                d.getState() == DependencyNode.INCLUDED) {
                return d;
            }
        }

        return null;
    }

    public static class ArtifactDependencyEntry {

        protected final Artifact artifact;

        protected final String artifactKey;

        protected DependencyNode node;

        protected List depIds;

        public ArtifactDependencyEntry(Artifact artifact) {
            this.artifact = artifact;
            artifactKey = getArtifactId(artifact);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy