org.apache.ignite.compatibility.testframework.util.MavenUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ignite.compatibility.testframework.util.MavenUtils.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.ignite.compatibility.testframework.util;

import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * Provides some useful methods to work with Maven.
 */
public class MavenUtils {
    /** Path to Maven local repository. For caching. */
    private static String locRepPath = null;

    /**
     * Gets a path to an artifact with given version and groupId=org.apache.ignite and artifactId=ignite-core.
     *
     * At first, artifact is looked for in the Maven local repository, if it isn't exists there, it will be downloaded
     * and stored via Maven.
     *
     * @param ver Version of ignite-core artifact.
     * @return Path to the artifact.
     * @throws Exception In case of an error.
     * @see #getPathToArtifact(String)
     */
    public static String getPathToIgniteCoreArtifact(@NotNull String ver) throws Exception {
        return getPathToIgniteCoreArtifact(ver, null);
    }

    /**
     * Gets a path to an artifact with given version and groupId=org.apache.ignite and artifactId=ignite-core.
     *
     * At first, artifact is looked for in the Maven local repository, if it isn't exists there, it will be downloaded
     * and stored via Maven.
     *
     * @param ver Version of ignite-core artifact.
     * @param classifier Artifact classifier.
     * @return Path to the artifact.
     * @throws Exception In case of an error.
     * @see #getPathToArtifact(String)
     */
    public static String getPathToIgniteCoreArtifact(@NotNull String ver, @Nullable String classifier)
            throws Exception {
        String artifact = "org.apache.ignite:ignite-core:" + ver;

        if (classifier != null)
            artifact += ":jar:" + classifier;

        return getPathToArtifact(artifact);
    }

    /**
     * Gets a path to an artifact with given identifier.
     *
     * At first, artifact is looked for in the Maven local repository, if it isn't exists there, it will be downloaded
     * and stored via Maven.
     *
     * @param artifact Artifact identifier, must match pattern [groupId:artifactId:version[:packaging[:classifier]]].
     * @return Path to the artifact.
     * @throws Exception In case of an error.
     */
    public static String getPathToArtifact(@NotNull String artifact) throws Exception {
        String[] names = artifact.split(":");

        assert names.length >= 3;

        String groupId = names[0];
        String artifactId = names[1];
        String version = names[2];
        String packaging = names.length > 3 ? names[3] : null;
        String classifier = names.length > 4 ? names[4] : null;

        String jarFileName = String.format("%s-%s%s.%s", artifactId, version,
                (classifier == null ? "" : "-" + classifier), (packaging == null ? "jar" : packaging));

        String pathToArtifact = getMavenLocalRepositoryPath() + File.separator
                + groupId.replace(".", File.separator) + File.separator + artifactId.replace(".", File.separator)
                + File.separator + version + File.separator + jarFileName;

        if (Files.notExists(Paths.get(pathToArtifact)))
            downloadArtifact(artifact);

        return pathToArtifact;
    }

    /**
     * Gets a path to the Maven local repository.
     *
     * @return Path to the Maven local repository.
     * @throws Exception In case of an error.
     */
    public static String getMavenLocalRepositoryPath() throws Exception {
        if (locRepPath == null)
            locRepPath = defineMavenLocalRepositoryPath();

        return locRepPath;
    }

    /**
     * Defines a path to the Maven local repository.
     *
     * @return Path to the Maven local repository.
     * @throws Exception In case of an error.
     */
    private static String defineMavenLocalRepositoryPath() throws Exception {
        String output = exec("mvn help:effective-settings");

        int endTagPos = output.indexOf("</localRepository>");

        assert endTagPos >= 0 : "Couldn't define path to Maven local repository";

        return output.substring(output.lastIndexOf(">", endTagPos) + 1, endTagPos);
    }

    /**
     * Downloads and stores in local repository an artifact with given identifier.
     *
     * @param artifact Artifact identifier, must match pattern [groupId:artifactId:version].
     * @throws Exception In case of an error.
     */
    private static void downloadArtifact(String artifact) throws Exception {
        X.println("Downloading artifact... Identifier: " + artifact);

        exec("mvn dependency:get -Dartifact=" + artifact);

        X.println("Download is finished");
    }

    /**
     * Executes given command in operation system.
     *
     * @param cmd Command to execute.
     * @return Output of result of executed command.
     * @throws Exception In case of an error.
     */
    private static String exec(String cmd) throws Exception {
        ProcessBuilder pb = new ProcessBuilder();
        pb.redirectErrorStream(true);

        pb.command(U.isWindows() ? new String[] { "cmd", "/c", cmd } : new String[] { "/bin/bash", "-c", cmd });

        final Process p = pb.start();

        Future<String> fut = Executors.newSingleThreadExecutor().submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                String output = CharStreams.toString(new InputStreamReader(p.getInputStream(), Charsets.UTF_8));

                p.waitFor();

                return output;
            }
        });

        String output = null;

        try {
            output = fut.get(5, TimeUnit.MINUTES);

            int exitVal = p.exitValue();

            if (exitVal != 0)
                throw new Exception(String.format("Abnormal exit value of %s for pid %s", exitVal, U.jvmPid()));

            return output;
        } catch (Exception e) {
            p.destroy();

            X.printerrln("Command='" + cmd + "' couldn't be executed: " + output, Charsets.UTF_8, e);

            throw e;
        }
    }
}