/*
* Copyright 2010 Outerthought bvba
*
* Licensed 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.lilyproject.tools.mavenplugin.hbaseexclusions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
/**
* This is a temporary Maven plugin used in the lily-hbase-client project to check that there are no
* redundant dependencies. Otherwise prints out the necessary exclusion-statements and fails the build.
*
* <p>This will be invalidated once there is a solution for this issue:
* https://issues.apache.org/jira/browse/HBASE-2170
*
* @requiresDependencyResolution runtime
* @goal generate-exclusions
*/
public class HBaseExclusionsMojo extends AbstractMojo {
/**
* @parameter default-value="${project}"
* @readonly
* @required
*/
private MavenProject project;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
List<Artifact> dependencies = (List<Artifact>)project.getRuntimeArtifacts();
// excludes grouped by parent artifact
Map<String, List<Artifact>> excludesByParent = new HashMap<String, List<Artifact>>();
for (Artifact artifact : dependencies) {
// Rather than simply outputting all dependencies as excludes, we only want to output
// an exclude for the direct children of the allowed artifact, because the other ones
// will be disabled recursively by Maven.
int allowedParentPos = getAllowedParentPostion(artifact.getDependencyTrail());
if (allowedParentPos != -1 && allowedParentPos == artifact.getDependencyTrail().size() - 2) {
// entry at level 0 in dependency trail is the project itself, entry at position 1 the
// dependencies listed in the pom, and deeper are the recursive deps
String topLevelParent = (String)artifact.getDependencyTrail().get(1);
List<Artifact> excludes = excludesByParent.get(topLevelParent);
if (excludes == null) {
excludes = new ArrayList<Artifact>();
excludesByParent.put(topLevelParent, excludes);
}
excludes.add(artifact);
}
}
if (excludesByParent.size() > 0) {
System.out.println();
System.out.println();
System.out.println();
System.out.println("Please add these excludes to the lily-hbase-client pom:");
System.out.println();
System.out.println();
for (Map.Entry<String, List<Artifact>> entry : excludesByParent.entrySet()) {
System.out.println("<dependency>");
String[] artifactParts = parseArtifactName(entry.getKey());
System.out.println(" <groupId>" + artifactParts[0] + "</groupId>");
System.out.println(" <artifactId>" + artifactParts[1] + "</artifactId>");
System.out.println(" <exclusions>");
for (Artifact artifact : entry.getValue()) {
System.out.println(" <exclusion>");
System.out.println(" <groupId>" + artifact.getGroupId() + "</groupId>");
System.out.println(" <artifactId>" + artifact.getArtifactId() + "</artifactId>");
System.out.println(" </exclusion>");
}
System.out.println(" <exclusions>");
System.out.println("</dependency>");
}
System.out.println();
System.out.println();
System.out.println();
throw new MojoExecutionException("lily-hbase-client is missing some excludes, please adjust");
}
}
private int getAllowedParentPostion(List<String> trail) {
for (int i = trail.size() - 1; i >= 0; i--) {
String artifact = trail.get(i);
String[] artifactParts = parseArtifactName(artifact);
if (isAllowed(artifactParts[0], artifactParts[1])) {
return i;
}
}
return -1;
}
private String[] parseArtifactName(String artifact) {
int groupIdEnd = artifact.indexOf(':');
String groupId = artifact.substring(0, groupIdEnd);
int artifactIdEnd = artifact.indexOf(':', groupIdEnd + 1);
String artifactId = artifact.substring(groupIdEnd + 1, artifactIdEnd);
return new String[] { groupId, artifactId };
}
private static final Set<String> ALLOWED_ARTIFACTS = new HashSet<String>();
static {
ALLOWED_ARTIFACTS.add("org.apache.hbase:hbase");
ALLOWED_ARTIFACTS.add("org.apache.hadoop:zookeeper");
ALLOWED_ARTIFACTS.add("org.apache.hadoop:hadoop-core");
ALLOWED_ARTIFACTS.add("org.apache.hadoop:hadoop-common");
ALLOWED_ARTIFACTS.add("org.apache.hadoop:hadoop-hdfs");
ALLOWED_ARTIFACTS.add("com.google.guava:guava");
ALLOWED_ARTIFACTS.add("org.apache.hadoop.thirdparty.guava:guava");
ALLOWED_ARTIFACTS.add("org.apache.zookeeper:zookeeper");
ALLOWED_ARTIFACTS.add("commons-configuration:commons-configuration");
ALLOWED_ARTIFACTS.add("org.apache.hadoop:hadoop-auth");
ALLOWED_ARTIFACTS.add("com.google.protobuf:protobuf-java");
ALLOWED_ARTIFACTS.add("com.github.stephenc.high-scale-lib:high-scale-lib");
ALLOWED_ARTIFACTS.add("commons-lang:commons-lang");
ALLOWED_ARTIFACTS.add("commons-cli:commons-cli"); // required by hdfs DFSClient constructor
ALLOWED_ARTIFACTS.add("commons-collections:commons-collections");
ALLOWED_ARTIFACTS.add("org.codehaus.jackson:jackson-core-asl");
ALLOWED_ARTIFACTS.add("org.codehaus.jackson:jackson-mapper-asl");
}
private boolean isAllowed(String groupId, String artifactId) {
return ALLOWED_ARTIFACTS.contains(groupId + ":" + artifactId);
}
}