blob: 81331ab4a0750c784620bc4a20f818aff0dfc268 [file] [log] [blame]
/*
* 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 java.io.File;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
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 com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.SB;
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;
/** */
private static final String GG_MVN_REPO = "http://www.gridgainsystems.com/nexus/content/repositories/external";
/** Set this flag to true if running PDS compatibility tests locally. */
private static boolean useGgRepo;
/**
* Gets a path to an artifact with given version and groupId=org.apache.ignite and artifactId={@code artifactId}.
* <br>
* 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.
* <br>
*
* @param groupId group name, e.g. 'org.apache.ignite'.
* @param ver Version of ignite or 3rd party library artifact.
* @param classifier Artifact classifier.
* @return Path to the artifact.
* @throws Exception In case of an error.
* @see #getPathToArtifact(String)
*/
public static String getPathToIgniteArtifact(@NotNull String groupId,
@NotNull String artifactId, @NotNull String ver,
@Nullable String classifier) throws Exception {
String artifact = groupId +
":" + artifactId + ":" + 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(buildMvnCommand() + " 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);
// Default platform independ path for maven settings file.
Path localProxyMavenSettings = Paths.get(System.getProperty("user.home"), ".m2", "local-proxy.xml");
String localProxyMavenSettingsFromEnv = System.getenv("LOCAL_PROXY_MAVEN_SETTINGS");
SB mavenCommandArgs = new SB(" org.apache.maven.plugins:maven-dependency-plugin:3.0.2:get -Dartifact=" + artifact);
if (!F.isEmpty(localProxyMavenSettingsFromEnv))
localProxyMavenSettings = Paths.get(localProxyMavenSettingsFromEnv);
if (Files.exists(localProxyMavenSettings))
mavenCommandArgs.a(" -s " + localProxyMavenSettings.toString());
else
mavenCommandArgs.a(useGgRepo ? " -DremoteRepositories=" + GG_MVN_REPO : "");
exec(buildMvnCommand() + mavenCommandArgs.toString());
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;
}
}
/**
* @return Maven executable command.
*/
private static String buildMvnCommand() {
String m2Home = System.getenv("M2_HOME");
if (m2Home == null)
m2Home = System.getProperty("M2_HOME");
if (m2Home == null)
return "mvn";
return m2Home + "/bin/mvn";
}
}