org.eclipse.skalli.model.ext.maven.internal.MavenResolver.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.skalli.model.ext.maven.internal.MavenResolver.java

Source

/*******************************************************************************
 * Copyright (c) 2010-2014 SAP AG and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     SAP AG - initial API and implementation
 *******************************************************************************/
package org.eclipse.skalli.model.ext.maven.internal;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;

import org.apache.commons.io.FilenameUtils;
import org.eclipse.skalli.model.Issuer;
import org.eclipse.skalli.model.ValidationException;
import org.eclipse.skalli.model.ext.devinf.DevInfProjectExt;
import org.eclipse.skalli.model.ext.maven.MavenModule;
import org.eclipse.skalli.model.ext.maven.MavenPomResolver;
import org.eclipse.skalli.model.ext.maven.MavenReactor;

public class MavenResolver implements Issuer {

    protected final UUID project;
    protected final MavenPomResolver pomResolver;

    /**
     * Creates a resolver for a given project.
     * @param project  the unique identifier of the project for which reactor information is to be calculated.
     * @param pomResolver  the path resolver to use to convert resource paths to download URLs.
     */
    public MavenResolver(UUID project, MavenPomResolver pomResolver) {
        this.project = project;
        this.pomResolver = pomResolver;
    }

    /**
     * Resolves a Maven reactor project and its modules.
     *
     * Note, this method assumes, that the POM files downloaded from the SCM system are
     * syntactically and semantically correct and complete. No attempt is made to validate
     * the returned <code>MavenReactor</code> instance. It may therefore contain incomplete
     * or invalid information.
     *
     * @param reactorPomPath  the path relative to the repository root of the reactor POM file
     * (without leading or trailing slashes and without file namne).
     * @param scmLocation  the SCM location provided by the
     * project (see {@link DevInfProjectExt#getScmLocation()}.
     *
     * @throws IOException  if an i/o error occured, e.g. the connection to the server
     * providing POM files cannot be established or is lost.
     * @throws ValidationException  if any of the relevant POMs is invalid or cannot be parsed.
     * @throws IllegalArgumentException  if the given SCM location cannot be resolved by
     * the path resolver assigned to this <code>MavenResolver</code> instance.
     */
    public MavenReactor resolve(String scmLocation, String reactorPomPath) throws IOException, ValidationException {
        MavenReactor mavenReactor = new MavenReactor();
        MavenPom reactorPom = pomResolver.getMavenPom(project, scmLocation, reactorPomPath);
        if (reactorPom == null) {
            throw new ValidationException(MessageFormat.format("no pom for scm location {0} and reactorPomPath {1}",
                    scmLocation, reactorPomPath));
        }
        MavenModule parent = reactorPom.getParent();
        MavenModule self = getSelf(reactorPom, parent);
        mavenReactor.setCoordinate(self);

        Set<String> moduleTags = reactorPom.getModuleTags();
        for (String moduleTag : moduleTags) {
            String normalizedPath = getNormalizedPath(reactorPomPath, moduleTag);
            if (normalizedPath != null) {
                List<String> visitedPaths = new ArrayList<String>();
                visitedPaths.add(normalizedPath);
                mavenReactor.addModules(getModules(visitedPaths, scmLocation, normalizedPath, self));
            }
        }
        return mavenReactor;
    }

    private Set<MavenModule> getModules(List<String> visitedPaths, String scmLocation, String relativePath,
            MavenModule parent) throws IOException, ValidationException {
        TreeSet<MavenModule> result = new TreeSet<MavenModule>();
        MavenPom modulePom = pomResolver.getMavenPom(project, scmLocation, relativePath);
        if (modulePom == null) {
            return result;
        }
        MavenModule self = getSelf(modulePom, parent);
        result.add(self);
        Set<String> moduleTags = modulePom.getModuleTags();
        for (String moduleTag : moduleTags) {
            String normalizedPath = getNormalizedPath(relativePath, moduleTag);
            if (normalizedPath != null && !visitedPaths.contains(normalizedPath)) {
                visitedPaths.add(normalizedPath);
                result.addAll(getModules(visitedPaths, scmLocation, normalizedPath, self));
            }
        }
        return result;
    }

    /**
     * Concats <code>pathPrefix</code> and <code>path</code>, normalizes the result by
     * removing double and single dot path segments, converts all file separators to forward slashes
     * and removes a leading slash, if any.
     *
     * @param pathPrefix  the path prefix.
     * @param path  the path relative to the path prefix.
     * @return  the bnormalized path, or <code>null</code> of removing double and single dot path
     * segments yielded an invalid path, e.g. a path like <tt>"foo/../../bar"</tt> would be treated
     * as invalid.
     */
    private String getNormalizedPath(String pathPrefix, String path) {
        String normalizedPath = FilenameUtils.normalize(pathPrefix + "/" + path); //$NON-NLS-1$
        if (normalizedPath == null) {
            return null;
        }
        normalizedPath = FilenameUtils.separatorsToUnix(normalizedPath);
        if (normalizedPath.charAt(0) == '/') {
            normalizedPath = normalizedPath.substring(1);
        }
        return normalizedPath;
    }

    private MavenModule getSelf(MavenPom mavenPom, MavenModule parent) {
        MavenModule self = mavenPom.getSelf();
        if (parent != null) {
            if (self.getGroupId() == null) {
                self.setGroupId(parent.getGroupId());
            }
        }
        return self;
    }

}