org.commonjava.maven.ext.manip.util.PomPeek.java Source code

Java tutorial

Introduction

Here is the source code for org.commonjava.maven.ext.manip.util.PomPeek.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Red Hat, Inc..
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.commonjava.maven.ext.manip.util;

import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.StringUtils.join;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.commonjava.maven.atlas.ident.ref.ProjectVersionRef;

public class PomPeek {
    private static final String G = "g";

    private static final String A = "a";

    private static final String V = "v";

    private static final String PG = "pg";

    private static final String PA = "pa";

    private static final String PV = "pv";

    private static final String PKG = "pkg";

    private static final String PRP = "prp";

    private static final String[] COORD_KEYS = { G, A, V, PG, PA, PV, PKG, PRP };

    private static final String MODULE_ELEM = "module";

    private static final String MODULES_ELEM = "modules";

    private static final Map<String, String> CAPTURED_PATHS = new HashMap<String, String>() {
        private static final long serialVersionUID = 1L;

        {
            put("project:groupId", G);
            put("project:artifactId", A);
            put("project:version", V);
            put("project:packaging", PKG);
            put("project:parent:groupId", PG);
            put("project:parent:artifactId", PA);
            put("project:parent:version", PV);
            put("project:parent:relativePath", PRP);
        }
    };

    @Requirement
    private Logger logger;

    private ProjectVersionRef key;

    private final Map<String, String> elementValues = new HashMap<String, String>();

    private final Set<String> modules = new HashSet<String>();

    private final File pom;

    private ProjectVersionRef parentKey;

    private boolean modulesDone = false;

    /**
     * Denotes if this represents the top level peeked POM.
     */
    private boolean topPOM = false;

    public PomPeek(final File pom) {
        this.pom = pom;
        parseCoordElements(pom);

        if (!createCoordinateInfo()) {
            logger.warn("Could not peek at POM coordinate for: " + pom
                    + "This POM will NOT be available as an ancestor to other models during effective-model building.");
        }
    }

    public String getParentRelativePath() {
        return elementValues.get(PRP);
    }

    public Set<String> getModules() {
        return modules;
    }

    public File getPom() {
        return pom;
    }

    public ProjectVersionRef getKey() {
        return key;
    }

    public ProjectVersionRef getParentKey() {
        return parentKey;
    }

    private void parseCoordElements(final File pom) {
        Reader reader = null;
        XMLStreamReader xml = null;
        try {
            reader = new FileReader(pom);
            xml = XMLInputFactory.newFactory().createXMLStreamReader(reader);

            final Stack<String> path = new Stack<String>();
            while (xml.hasNext()) {
                final int evt = xml.next();
                switch (evt) {
                case START_ELEMENT: {
                    final String elem = xml.getLocalName();
                    path.push(elem);
                    if (captureValue(elem, path, xml)) {
                        // seems like xml.getElementText() traverses the END_ELEMENT event...
                        path.pop();
                    }
                    break;
                }
                case END_ELEMENT: {
                    final String elem = xml.getLocalName();
                    if (MODULES_ELEM.equals(elem)) {
                        modulesDone = true;
                    }

                    path.pop();
                    break;
                }
                default: {
                }
                }

                if (foundAll()) {
                    return;
                }
            }
        } catch (final IOException e) {
            logger.warn("Failed to peek at POM coordinate for: " + pom + " Reason: " + e.getMessage()
                    + "\nThis POM will NOT be available as an ancestor to other models during effective-model building.",
                    e);
        } catch (final XMLStreamException e) {
            logger.warn("Failed to peek at POM coordinate for: " + pom + " Reason: " + e.getMessage()
                    + "\nThis POM will NOT be available as an ancestor to other models during effective-model building.",
                    e);
        } catch (final FactoryConfigurationError e) {
            logger.warn("Failed to peek at POM coordinate for: " + pom + " Reason: " + e.getMessage()
                    + "\nThis POM will NOT be available as an ancestor to other models during effective-model building.",
                    e);
        } finally {
            if (xml != null) {
                try {
                    xml.close();
                } catch (final XMLStreamException e) {
                }
            }

            try {
                reader.close();
            } catch (final IOException ioe) {
            }
        }
    }

    private boolean foundAll() {
        for (final String key : COORD_KEYS) {
            if (!elementValues.containsKey(key)) {
                return false;
            }
        }

        if ("pom".equals(elementValues.get(PKG)) && !modulesDone) {
            return false;
        }

        return true;
    }

    private boolean captureValue(final String elem, final Stack<String> path, final XMLStreamReader xml)
            throws XMLStreamException {
        final String pathStr = join(path, ":");
        final String key = CAPTURED_PATHS.get(pathStr);
        if (key != null) {
            elementValues.put(key, xml.getElementText().trim());

            return true;
        } else if (MODULE_ELEM.equals(elem)) {
            modules.add(xml.getElementText().trim());
        }

        return false;
    }

    private boolean createCoordinateInfo() {
        String v = elementValues.get(V);
        final String pv = elementValues.get(PV);
        if (isEmpty(v)) {
            v = pv;
        }

        String g = elementValues.get(G);
        final String pg = elementValues.get(PG);
        if (isEmpty(g)) {
            g = pg;
        }

        final String a = elementValues.get(A);
        final String pa = elementValues.get(PA);

        boolean valid = false;
        if (isValidArtifactId(a) && isValidGroupId(g) && isValidVersion(v)) {
            key = new ProjectVersionRef(g, a, v);
            valid = true;
        }

        if (isValidArtifactId(pa) && isValidGroupId(pg) && isValidVersion(pv)) {
            parentKey = new ProjectVersionRef(pg, pa, pv);
        }

        return valid;
    }

    private boolean isValidVersion(final String version) {
        if (isEmpty(version)) {
            return false;
        }

        if ("version".equals(version)) {
            return false;
        }

        if ("parentVersion".equals(version)) {
            return false;
        }

        return true;
    }

    private boolean isValidGroupId(final String groupId) {
        if (isEmpty(groupId)) {
            return false;
        }

        if (groupId.contains("${")) {
            return false;
        }

        if ("parentGroupId".equals(groupId)) {
            return false;
        }

        if ("groupId".equals(groupId)) {
            return false;
        }

        return true;
    }

    private boolean isValidArtifactId(final String artifactId) {
        if (isEmpty(artifactId)) {
            return false;
        }

        if (artifactId.contains("${")) {
            return false;
        }

        if ("parentArtifactId".equals(artifactId)) {
            return false;
        }

        if ("artifactId".equals(artifactId)) {
            return false;
        }

        return true;
    }

    public void setTopPOM(final boolean b) {
        topPOM = b;
    }

    public boolean isTopPOM() {
        return topPOM;
    }
}