com.redhat.rcm.version.mgr.capture.MissingInfoCapture.java Source code

Java tutorial

Introduction

Here is the source code for com.redhat.rcm.version.mgr.capture.MissingInfoCapture.java

Source

/*
 * Copyright (c) 2010 Red Hat, Inc.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see 
 * <http://www.gnu.org/licenses>.
 */

package com.redhat.rcm.version.mgr.capture;

import static org.apache.commons.io.IOUtils.closeQuietly;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.StringUtils.isNotEmpty;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.maven.mae.project.key.FullProjectKey;
import org.apache.maven.mae.project.key.VersionlessProjectKey;
import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.util.WriterFactory;
import org.sonatype.aether.artifact.ArtifactType;
import org.sonatype.aether.util.version.GenericVersionScheme;
import org.sonatype.aether.version.InvalidVersionSpecificationException;
import org.sonatype.aether.version.Version;
import org.sonatype.aether.version.VersionScheme;

import com.redhat.rcm.version.Cli;
import com.redhat.rcm.version.VManException;
import com.redhat.rcm.version.mgr.session.VersionManagerSession;
import com.redhat.rcm.version.model.DependencyManagementKey;
import com.redhat.rcm.version.model.Project;

@Component(role = MissingInfoCapture.class)
public class MissingInfoCapture {

    private static final String VERSION_DATE_PATTERN = "yyyyMMdd.HHmm";

    public void captureMissing(final VersionManagerSession session) {
        final Map<VersionlessProjectKey, Set<Dependency>> missingDeps = session.getMissingDependencies();
        final Map<VersionlessProjectKey, Set<Plugin>> missingPlugins = session.getUnmanagedPluginRefs();
        final Set<Project> missingParents = session.getProjectsWithMissingParent();
        final Map<String, String> missingVersionProps = session.getMissingVersionProperties();

        final boolean procDeps = notEmpty(missingDeps);
        final boolean procPlugs = notEmpty(missingPlugins);
        final boolean procParents = notEmpty(missingParents);
        final boolean procProps = notEmpty(missingVersionProps);

        if (procProps || procDeps || procPlugs) {
            final SimpleDateFormat format = new SimpleDateFormat(VERSION_DATE_PATTERN);
            final Model model = new Model();
            model.setModelVersion("4.0.0");

            model.setGroupId(Cli.class.getPackage().getName());
            model.setArtifactId("vman-missing-capture");
            model.setVersion(format.format(new Date()));

            model.setPackaging("pom");

            boolean write = false;

            write = processCurrentProjects(session, model) || write;

            if (procProps) {
                write = processProperties(missingVersionProps, model) || write;
            }

            if (procDeps) {
                write = processDependencies(missingDeps, model) || write;
            }

            if (procPlugs) {
                write = processPlugins(missingPlugins, model) || write;
            }

            if (procParents) {
                write = processParents(missingParents, model) || write;
            }

            if (write) {
                final File capturePom = session.getCapturePom();
                Writer writer = null;
                try {
                    final File dir = capturePom.getAbsoluteFile().getParentFile();
                    if (dir != null && !dir.exists()) {
                        dir.mkdirs();
                    }

                    writer = WriterFactory.newXmlWriter(capturePom);
                    new MavenXpp3Writer().write(writer, model);
                } catch (final IOException e) {
                    session.addError(new VManException("Failed to write capture POM: %s. Reason: %s", e, capturePom,
                            e.getMessage()));
                } finally {
                    closeQuietly(writer);
                }
            }
        }
    }

    private boolean processProperties(final Map<String, String> props, final Model model) {
        for (final Map.Entry<String, String> entry : props.entrySet()) {
            model.getProperties().setProperty(entry.getKey(), entry.getValue());
        }

        return true;
    }

    private boolean processCurrentProjects(final VersionManagerSession session, final Model model) {
        final DependencyManagement dm = getDependencyManagement(model);
        boolean changed = false;
        for (final Project project : session.getCurrentProjects()) {
            final Dependency managed = session.getManagedDependency(
                    new DependencyManagementKey(project.getGroupId(), project.getArtifactId(), "pom", null));
            if (managed == null) {
                final Dependency dep = new Dependency();
                dep.setGroupId(project.getGroupId());
                dep.setArtifactId(project.getArtifactId());
                dep.setVersion(project.getVersion());

                final ArtifactType at = session.getArtifactType(project);
                if (at != null) {
                    dep.setType(at.getExtension());
                    dep.setClassifier(at.getClassifier());
                } else {
                    dep.setType(project.getPackaging());
                }

                dm.addDependency(dep);
                changed = true;
            }
        }

        return changed;
    }

    private boolean processParents(final Set<Project> missingParents, final Model model) {
        final DependencyManagement dm = getDependencyManagement(model);

        final Map<FullProjectKey, Dependency> parents = new HashMap<FullProjectKey, Dependency>();
        for (final Project project : missingParents) {
            final Parent parent = project.getParent();

            final FullProjectKey key = new FullProjectKey(parent);
            if (!parents.containsKey(key)) {
                final Dependency dep = new Dependency();
                dep.setGroupId(parent.getGroupId());
                dep.setArtifactId(parent.getArtifactId());
                dep.setVersion(parent.getVersion());

                parents.put(key, dep);
            }
        }

        final Set<FullProjectKey> depKeys = new HashSet<FullProjectKey>();
        for (final Dependency dep : dm.getDependencies()) {
            depKeys.add(new FullProjectKey(dep));
        }

        boolean result = false;
        for (final Map.Entry<FullProjectKey, Dependency> entry : parents.entrySet()) {
            if (!depKeys.contains(entry.getKey())) {
                dm.addDependency(entry.getValue());
                result = true;
            }
        }

        return result;
    }

    private DependencyManagement getDependencyManagement(final Model model) {
        DependencyManagement dm = model.getDependencyManagement();
        if (dm == null) {
            dm = new DependencyManagement();
            model.setDependencyManagement(dm);
        }

        return dm;
    }

    private boolean processPlugins(final Map<VersionlessProjectKey, Set<Plugin>> missingPlugins,
            final Model model) {
        final Build build = new Build();
        final PluginManagement pm = new PluginManagement();
        build.setPluginManagement(pm);

        for (final Map.Entry<VersionlessProjectKey, Set<Plugin>> entry : missingPlugins.entrySet()) {
            final Map<String, Set<Plugin>> mks = new HashMap<String, Set<Plugin>>();
            for (final Plugin plugin : entry.getValue()) {
                final String key = plugin.getKey();
                Set<Plugin> ds = mks.get(key);
                if (ds == null) {
                    ds = new HashSet<Plugin>();
                    mks.put(key, ds);
                }

                ds.add(plugin);
            }

            for (final Set<Plugin> ds : mks.values()) {
                if (ds == null || ds.isEmpty()) {
                    continue;
                }

                final List<Plugin> pluginList = new ArrayList<Plugin>(ds);
                Collections.sort(pluginList, new PluginVersionComparator());

                pm.addPlugin(pluginList.get(0));
            }
        }

        if (pm.getPlugins() != null && !pm.getPlugins().isEmpty()) {
            Collections.sort(pm.getPlugins(), new PluginArtifactIdComparator());

            model.setBuild(build);
            return true;
        }

        return false;
    }

    private boolean processDependencies(final Map<VersionlessProjectKey, Set<Dependency>> missingDeps,
            final Model model) {
        final DependencyManagement dm = getDependencyManagement(model);

        for (final Map.Entry<VersionlessProjectKey, Set<Dependency>> entry : missingDeps.entrySet()) {
            final Map<String, Set<Dependency>> mks = new HashMap<String, Set<Dependency>>();
            for (final Dependency dep : entry.getValue()) {
                final String key = dep.getManagementKey();
                Set<Dependency> ds = mks.get(key);
                if (ds == null) {
                    ds = new HashSet<Dependency>();
                    mks.put(key, ds);
                }

                ds.add(dep);
            }

            for (final Set<Dependency> ds : mks.values()) {
                if (ds == null || ds.isEmpty()) {
                    continue;
                }

                final List<Dependency> depList = new ArrayList<Dependency>(ds);
                Collections.sort(depList, new DependencyVersionComparator());

                dm.addDependency(depList.get(0));
            }
        }

        if (dm.getDependencies() != null && !dm.getDependencies().isEmpty()) {
            Collections.sort(dm.getDependencies(), new DependencyArtifactIdComparator());

            model.setDependencyManagement(dm);
            return true;
        }

        return false;
    }

    private boolean notEmpty(final Map<?, ?> map) {
        return map != null && !map.isEmpty();
    }

    private boolean notEmpty(final Collection<?> coll) {
        return coll != null && !coll.isEmpty();
    }

    public static final class DependencyVersionComparator implements Comparator<Dependency> {

        private final VersionScheme versionScheme = new GenericVersionScheme();

        @Override
        public int compare(final Dependency o1, final Dependency o2) {
            int result = 0;

            if (isEmpty(o1.getVersion()) && isNotEmpty(o2.getVersion())) {
                result = -1;
            } else if (isNotEmpty(o1.getVersion()) && isEmpty(o2.getVersion())) {
                result = 1;
            } else {
                Version v1 = null;
                try {
                    v1 = versionScheme.parseVersion(o1.getVersion());
                } catch (final InvalidVersionSpecificationException e) {
                    result = -1;
                }

                if (v1 != null) {
                    try {
                        final Version v2 = versionScheme.parseVersion(o2.getVersion());

                        result = v1.compareTo(v2);
                    } catch (final InvalidVersionSpecificationException e) {
                        result = 1;
                    }
                }

            }

            return result;
        }

    }

    public static final class PluginVersionComparator implements Comparator<Plugin> {

        private final VersionScheme versionScheme = new GenericVersionScheme();

        @Override
        public int compare(final Plugin o1, final Plugin o2) {
            int result = 0;

            if (isEmpty(o1.getVersion()) && isNotEmpty(o2.getVersion())) {
                result = -1;
            } else if (isNotEmpty(o1.getVersion()) && isEmpty(o2.getVersion())) {
                result = 1;
            } else {
                Version v1 = null;
                try {
                    v1 = versionScheme.parseVersion(o1.getVersion());
                } catch (final InvalidVersionSpecificationException e) {
                    result = -1;
                }

                if (v1 != null) {
                    try {
                        final Version v2 = versionScheme.parseVersion(o2.getVersion());

                        result = v1.compareTo(v2);
                    } catch (final InvalidVersionSpecificationException e) {
                        result = 1;
                    }
                }

            }

            return result;
        }

    }

    public class DependencyArtifactIdComparator implements Comparator<Dependency> {
        @Override
        public int compare(final Dependency o1, final Dependency o2) {
            return o1.getArtifactId().compareTo(o2.getArtifactId());
        }
    }

    public class PluginArtifactIdComparator implements Comparator<Plugin> {
        @Override
        public int compare(final Plugin o1, final Plugin o2) {
            return o1.getArtifactId().compareTo(o2.getArtifactId());
        }
    }

}