Search in sources :

Example 11 with ClassPathEntry

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);
    }
}
Also used : Path(java.nio.file.Path) DependencyPath(com.google.cloud.tools.opensource.dependencies.DependencyPath) AnnotatedClassPath(com.google.cloud.tools.opensource.classpath.AnnotatedClassPath) RepositorySystemSession(org.eclipse.aether.RepositorySystemSession) DefaultRepositorySystemSession(org.eclipse.aether.DefaultRepositorySystemSession) ExpressionEvaluationException(org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException) LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem) EnforcerRuleException(org.apache.maven.enforcer.rule.api.EnforcerRuleException) ClassPathBuilder(com.google.cloud.tools.opensource.classpath.ClassPathBuilder) ClassPathResult(com.google.cloud.tools.opensource.classpath.ClassPathResult) IOException(java.io.IOException) ClassPathEntry(com.google.cloud.tools.opensource.classpath.ClassPathEntry) ClassReferenceGraph(com.google.cloud.tools.opensource.classpath.ClassReferenceGraph) MavenSession(org.apache.maven.execution.MavenSession) MavenProject(org.apache.maven.project.MavenProject) MojoExecution(org.apache.maven.plugin.MojoExecution) DependencyGraphBuilder(com.google.cloud.tools.opensource.dependencies.DependencyGraphBuilder) LinkageChecker(com.google.cloud.tools.opensource.classpath.LinkageChecker)

Example 12 with ClassPathEntry

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;
}
Also used : Path(java.nio.file.Path) DependencyPath(com.google.cloud.tools.opensource.dependencies.DependencyPath) LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem) GradleDependencyMediation(com.google.cloud.tools.opensource.classpath.GradleDependencyMediation) DependencyMediation(com.google.cloud.tools.opensource.classpath.DependencyMediation) ClassPathResult(com.google.cloud.tools.opensource.classpath.ClassPathResult) LinkageChecker(com.google.cloud.tools.opensource.classpath.LinkageChecker) Artifact(org.eclipse.aether.artifact.Artifact) DefaultArtifact(org.eclipse.aether.artifact.DefaultArtifact) ClassPathEntry(com.google.cloud.tools.opensource.classpath.ClassPathEntry)

Example 13 with ClassPathEntry

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);
}
Also used : LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem) ClassFile(com.google.cloud.tools.opensource.classpath.ClassFile) ClassNotFoundProblem(com.google.cloud.tools.opensource.classpath.ClassNotFoundProblem) ClassSymbol(com.google.cloud.tools.opensource.classpath.ClassSymbol) ClassFile(com.google.cloud.tools.opensource.classpath.ClassFile) File(java.io.File) DefaultArtifact(org.eclipse.aether.artifact.DefaultArtifact) Artifact(org.eclipse.aether.artifact.Artifact) DefaultArtifact(org.eclipse.aether.artifact.DefaultArtifact) ClassPathEntry(com.google.cloud.tools.opensource.classpath.ClassPathEntry) Before(org.junit.Before)

Example 14 with ClassPathEntry

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());
}
Also used : HashMap(java.util.HashMap) ClassPathBuilder(com.google.cloud.tools.opensource.classpath.ClassPathBuilder) ClassPathResult(com.google.cloud.tools.opensource.classpath.ClassPathResult) ClassPathEntry(com.google.cloud.tools.opensource.classpath.ClassPathEntry) Artifact(org.eclipse.aether.artifact.Artifact)

Example 15 with ClassPathEntry

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();
}
Also used : Version(org.eclipse.aether.version.Version) ImmutableList(com.google.common.collect.ImmutableList) ClassPathBuilder(com.google.cloud.tools.opensource.classpath.ClassPathBuilder) ClassPathResult(com.google.cloud.tools.opensource.classpath.ClassPathResult) ClassPathEntry(com.google.cloud.tools.opensource.classpath.ClassPathEntry) Artifact(org.eclipse.aether.artifact.Artifact)

Aggregations

ClassPathEntry (com.google.cloud.tools.opensource.classpath.ClassPathEntry)17 Artifact (org.eclipse.aether.artifact.Artifact)12 ClassPathResult (com.google.cloud.tools.opensource.classpath.ClassPathResult)10 DependencyPath (com.google.cloud.tools.opensource.dependencies.DependencyPath)8 ClassPathBuilder (com.google.cloud.tools.opensource.classpath.ClassPathBuilder)7 LinkageProblem (com.google.cloud.tools.opensource.classpath.LinkageProblem)7 DefaultArtifact (org.eclipse.aether.artifact.DefaultArtifact)7 AnnotatedClassPath (com.google.cloud.tools.opensource.classpath.AnnotatedClassPath)4 ImmutableList (com.google.common.collect.ImmutableList)4 Path (java.nio.file.Path)4 ClassFile (com.google.cloud.tools.opensource.classpath.ClassFile)3 LinkageChecker (com.google.cloud.tools.opensource.classpath.LinkageChecker)3 ImmutableSet (com.google.common.collect.ImmutableSet)3 DependencyGraph (com.google.cloud.tools.opensource.dependencies.DependencyGraph)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)2 File (java.io.File)2 IOException (java.io.IOException)2 HashMap (java.util.HashMap)2 EnforcerRuleException (org.apache.maven.enforcer.rule.api.EnforcerRuleException)2 Dependency (org.eclipse.aether.graph.Dependency)2