use of com.google.cloud.tools.opensource.classpath.ClassPathEntry in project cloud-opensource-java by GoogleCloudPlatform.
the class LinkageCheckerRule method execute.
@Override
public void execute(@Nonnull EnforcerRuleHelper helper) throws EnforcerRuleException {
logger = helper.getLog();
try {
MavenProject project = (MavenProject) helper.evaluate("${project}");
MavenSession session = (MavenSession) helper.evaluate("${session}");
MojoExecution execution = (MojoExecution) helper.evaluate("${mojoExecution}");
RepositorySystemSession repositorySystemSession = session.getRepositorySession();
ImmutableList<String> repositoryUrls = project.getRemoteProjectRepositories().stream().map(RemoteRepository::getUrl).collect(toImmutableList());
DependencyGraphBuilder dependencyGraphBuilder = new DependencyGraphBuilder(repositoryUrls);
classPathBuilder = new ClassPathBuilder(dependencyGraphBuilder);
boolean readingDependencyManagementSection = dependencySection == DependencySection.DEPENDENCY_MANAGEMENT;
if (readingDependencyManagementSection && (project.getDependencyManagement() == null || project.getDependencyManagement().getDependencies() == null || project.getDependencyManagement().getDependencies().isEmpty())) {
logger.warn("The rule is set to read dependency management section but it is empty.");
}
String projectType = project.getArtifact().getType();
if (readingDependencyManagementSection) {
if (!"pom".equals(projectType)) {
logger.warn("A BOM should have packaging pom");
return;
}
} else {
if (UNSUPPORTED_NONBOM_PACKAGING.contains(projectType)) {
return;
}
if (!"verify".equals(execution.getLifecyclePhase())) {
throw new EnforcerRuleException("To run the check on the compiled class files, the linkage checker enforcer rule" + " should be bound to the 'verify' phase. Current phase: " + execution.getLifecyclePhase());
}
if (project.getArtifact().getFile() == null) {
// https://github.com/GoogleCloudPlatform/cloud-opensource-java/issues/850
return;
}
}
ClassPathResult classPathResult = readingDependencyManagementSection ? findBomClasspath(project, repositorySystemSession) : findProjectClasspath(project, repositorySystemSession, helper);
ImmutableList<ClassPathEntry> classPath = classPathResult.getClassPath();
if (classPath.isEmpty()) {
logger.warn("Class path is empty.");
return;
}
List<ClassPathEntry> entryPoints = entryPoints(project, classPath);
try {
// TODO LinkageChecker.create and LinkageChecker.findLinkageProblems
// should not be two separate public methods since we always call
// findLinkageProblems immediately after create.
Path exclusionFile = this.exclusionFile == null ? null : Paths.get(this.exclusionFile);
LinkageChecker linkageChecker = LinkageChecker.create(classPath, entryPoints, exclusionFile);
ImmutableSet<LinkageProblem> linkageProblems = linkageChecker.findLinkageProblems();
if (reportOnlyReachable) {
ClassReferenceGraph classReferenceGraph = linkageChecker.getClassReferenceGraph();
linkageProblems = linkageProblems.stream().filter(entry -> classReferenceGraph.isReachable(entry.getSourceClass().getBinaryName())).collect(toImmutableSet());
}
if (classPathResult != null) {
LinkageProblemCauseAnnotator.annotate(classPathBuilder, classPathResult, linkageProblems);
}
// Count unique LinkageProblems by their symbols
long errorCount = linkageProblems.stream().map(LinkageProblem::formatSymbolProblem).distinct().count();
String foundError = reportOnlyReachable ? "reachable error" : "error";
if (errorCount > 1) {
foundError += "s";
}
if (errorCount > 0) {
String message = String.format("Linkage Checker rule found %d %s:\n%s", errorCount, foundError, LinkageProblem.formatLinkageProblems(linkageProblems, classPathResult));
if (getLevel() == WARN) {
logger.warn(message);
} else {
logger.error(message);
logger.info("For the details of the linkage errors, see " + "https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/Linkage-Checker-Messages");
throw new EnforcerRuleException("Failed while checking class path. See above error report.");
}
} else {
// arguably shouldn't log anything on success
logger.info("No " + foundError + " found");
}
} catch (IOException ex) {
// Maven's "-e" flag does not work for EnforcerRuleException. Print stack trace here.
logger.warn("Failed to run Linkage Checker:" + ex.getMessage(), ex);
throw new EnforcerRuleException("Failed to run Linkage Checker", ex);
}
} catch (ExpressionEvaluationException ex) {
throw new EnforcerRuleException("Unable to lookup an expression " + ex.getMessage(), ex);
}
}
use of com.google.cloud.tools.opensource.classpath.ClassPathEntry in project cloud-opensource-java by GoogleCloudPlatform.
the class DashboardMain method generate.
private static Path generate(Bom bom, DependencyMediationAlgorithm dependencyMediationAlgorithm) throws IOException, TemplateException, URISyntaxException, InvalidVersionSpecificationException {
ImmutableList<Artifact> managedDependencies = bom.getManagedDependencies();
DependencyMediation dependencyMediation = dependencyMediationAlgorithm == DependencyMediationAlgorithm.MAVEN ? DependencyMediation.MAVEN : GradleDependencyMediation.withEnforcedPlatform(bom);
ClassPathResult classPathResult = classPathBuilder.resolve(managedDependencies, false, dependencyMediation);
ImmutableList<ClassPathEntry> classpath = classPathResult.getClassPath();
LinkageChecker linkageChecker = LinkageChecker.create(classpath);
ImmutableSet<LinkageProblem> linkageProblems = linkageChecker.findLinkageProblems();
ArtifactCache cache = loadArtifactInfo(managedDependencies);
Path output = generateHtml(bom, cache, classPathResult, linkageProblems);
return output;
}
use of com.google.cloud.tools.opensource.classpath.ClassPathEntry in project cloud-opensource-java by GoogleCloudPlatform.
the class FreemarkerTest method setUp.
@Before
public void setUp() {
Artifact artifact = new DefaultArtifact("com.google:foo:1.0.0").setFile(new File("foo/bar-1.2.3.jar"));
ClassPathEntry entry = new ClassPathEntry(artifact);
ImmutableSet<LinkageProblem> dummyProblems = ImmutableSet.of(new ClassNotFoundProblem(new ClassFile(entry, "abc.def.G"), new ClassSymbol("com.foo.Bar")));
symbolProblemTable = ImmutableMap.of(entry, dummyProblems);
}
use of com.google.cloud.tools.opensource.classpath.ClassPathEntry in project cloud-opensource-java by GoogleCloudPlatform.
the class BomContentTest method assertUniqueClasses.
/**
* Asserts that the BOM only provides JARs which contains unique class names to the classpath.
*/
private static void assertUniqueClasses(List<Artifact> allArtifacts) throws InvalidVersionSpecificationException, IOException {
StringBuilder errorMessageBuilder = new StringBuilder();
ClassPathBuilder classPathBuilder = new ClassPathBuilder();
ClassPathResult result = classPathBuilder.resolve(allArtifacts, false, DependencyMediation.MAVEN);
// A Map of every class name to its artifact ID.
HashMap<String, String> fullClasspathMap = new HashMap<>();
for (ClassPathEntry classPathEntry : result.getClassPath()) {
Artifact currentArtifact = classPathEntry.getArtifact();
if (!currentArtifact.getGroupId().contains("google") || currentArtifact.getGroupId().contains("com.google.android") || currentArtifact.getGroupId().contains("com.google.cloud.bigtable") || currentArtifact.getArtifactId().startsWith("proto-") || currentArtifact.getArtifactId().equals("protobuf-javalite") || currentArtifact.getArtifactId().equals("appengine-testing")) {
// See: https://github.com/GoogleCloudPlatform/cloud-opensource-java/issues/2226
continue;
}
String artifactCoordinates = Artifacts.toCoordinates(currentArtifact);
for (String className : classPathEntry.getFileNames()) {
if (className.contains("javax.annotation") || className.contains("$") || className.equals("com.google.cloud.location.LocationsGrpc") || className.endsWith("package-info")) {
// Ignore LocationsGrpc classes which are duplicated in generated grpc libraries.
continue;
}
String previousArtifact = fullClasspathMap.get(className);
if (previousArtifact != null) {
String msg = String.format("Duplicate class %s found in classpath. Found in artifacts %s and %s.\n", className, previousArtifact, artifactCoordinates);
errorMessageBuilder.append(msg);
} else {
fullClasspathMap.put(className, artifactCoordinates);
}
}
}
String error = errorMessageBuilder.toString();
Assert.assertTrue("Failing test due to duplicate classes found on classpath:\n" + error, error.isEmpty());
}
use of com.google.cloud.tools.opensource.classpath.ClassPathEntry in project cloud-opensource-java by GoogleCloudPlatform.
the class BomContentTest method findNoDowngradeViolation.
/**
* Returns messages describing the violation of the no-downgrade rule by {@code artifact} against
* the BOM containing {@code bomArtifacts}. An empty list if there is no violations.
*/
private static ImmutableList<String> findNoDowngradeViolation(Map<String, Artifact> bomArtifacts, Artifact artifact) throws InvalidVersionSpecificationException {
ImmutableList.Builder<String> violations = ImmutableList.builder();
ClassPathBuilder classPathBuilder = new ClassPathBuilder();
ClassPathResult result = classPathBuilder.resolve(ImmutableList.of(artifact), false, DependencyMediation.MAVEN);
for (ClassPathEntry entry : result.getClassPath()) {
Artifact transitiveDependency = entry.getArtifact();
String key = Artifacts.makeKey(transitiveDependency);
Artifact bomArtifact = bomArtifacts.get(key);
if (bomArtifact == null) {
// transitiveDependency is not part of the BOM
continue;
}
Version versionInBom = versionScheme.parseVersion(bomArtifact.getVersion());
Version versionInTransitiveDependency = versionScheme.parseVersion(transitiveDependency.getVersion());
if (versionInTransitiveDependency.compareTo(versionInBom) <= 0) {
// the no-downgrade rule.
continue;
}
// A violation of the no-downgrade rule is found.
violations.add(artifact + " has a transitive dependency " + transitiveDependency + ". This is higher version than " + bomArtifact + " in the BOM");
}
return violations.build();
}
Aggregations