Search in sources :

Example 6 with ClassPathResult

use of com.google.cloud.tools.opensource.classpath.ClassPathResult in project cloud-opensource-java by GoogleCloudPlatform.

the class LinkageCheckTask method findLinkageErrors.

/**
 * Returns true iff {@code configuration}'s artifacts contain linkage errors.
 */
private boolean findLinkageErrors(Configuration configuration) throws IOException {
    ClassPathResult classPathResult = createClassPathResult(configuration.getResolvedConfiguration());
    ImmutableList.Builder<ClassPathEntry> classPathEntriesBuilder = ImmutableList.builder();
    for (ResolvedArtifact resolvedArtifact : configuration.getResolvedConfiguration().getResolvedArtifacts()) {
        ModuleVersionIdentifier moduleVersionId = resolvedArtifact.getModuleVersion().getId();
        DefaultArtifact artifact = new DefaultArtifact(moduleVersionId.getGroup(), moduleVersionId.getName(), resolvedArtifact.getClassifier(), resolvedArtifact.getExtension(), moduleVersionId.getVersion(), null, resolvedArtifact.getFile());
        classPathEntriesBuilder.add(new ClassPathEntry(artifact));
    }
    ImmutableList<ClassPathEntry> classPath = classPathEntriesBuilder.build();
    if (!classPath.isEmpty()) {
        String exclusionFileName = extension.getExclusionFile();
        Path exclusionFile = exclusionFileName == null ? null : Paths.get(exclusionFileName);
        if (exclusionFile != null && !exclusionFile.isAbsolute()) {
            // Relative path from the project root
            Path projectRoot = getProject().getRootDir().toPath();
            exclusionFile = projectRoot.resolve(exclusionFile).toAbsolutePath();
        }
        // TODO(suztomo): Specify correct entry points if reportOnlyReachable is true.
        LinkageChecker linkageChecker = LinkageChecker.create(classPath, classPath, exclusionFile);
        ImmutableSet<LinkageProblem> linkageProblems = linkageChecker.findLinkageProblems();
        ClassPathBuilder classPathBuilder = new ClassPathBuilder();
        LinkageProblemCauseAnnotator.annotate(classPathBuilder, classPathResult, linkageProblems);
        int errorCount = linkageProblems.size();
        // TODO(suztomo): Show the dependency paths to the problematic artifacts.
        if (errorCount > 0) {
            getLogger().error("Linkage Checker rule found {} error{}:\n{}", errorCount, errorCount > 1 ? "s" : "", LinkageProblem.formatLinkageProblems(linkageProblems, classPathResult));
            ResolutionResult result = configuration.getIncoming().getResolutionResult();
            ResolvedComponentResult root = result.getRoot();
            String dependencyPaths = dependencyPathsOfProblematicJars(root, linkageProblems);
            getLogger().error(dependencyPaths);
            getLogger().info("For the details of the linkage errors, see " + "https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/Linkage-Checker-Messages");
        }
        return errorCount > 0;
    }
    // When the configuration does not have any artifacts, there's no linkage error.
    return false;
}
Also used : AnnotatedClassPath(com.google.cloud.tools.opensource.classpath.AnnotatedClassPath) Path(java.nio.file.Path) DependencyPath(com.google.cloud.tools.opensource.dependencies.DependencyPath) ResolvedArtifact(org.gradle.api.artifacts.ResolvedArtifact) LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem) ImmutableList(com.google.common.collect.ImmutableList) ResolutionResult(org.gradle.api.artifacts.result.ResolutionResult) ClassPathResult(com.google.cloud.tools.opensource.classpath.ClassPathResult) ClassPathBuilder(com.google.cloud.tools.opensource.classpath.ClassPathBuilder) ClassPathEntry(com.google.cloud.tools.opensource.classpath.ClassPathEntry) ModuleVersionIdentifier(org.gradle.api.artifacts.ModuleVersionIdentifier) LinkageChecker(com.google.cloud.tools.opensource.classpath.LinkageChecker) ResolvedComponentResult(org.gradle.api.artifacts.result.ResolvedComponentResult) DefaultArtifact(org.eclipse.aether.artifact.DefaultArtifact)

Example 7 with ClassPathResult

use of com.google.cloud.tools.opensource.classpath.ClassPathResult in project cloud-opensource-java by GoogleCloudPlatform.

the class LinkageMonitor method run.

/**
 * Returns new problems in the BOM specified by {@code groupId} and {@code artifactId}. This
 * method compares the latest release of the BOM and its snapshot version which uses artifacts in
 * {@link #localArtifacts}.
 */
private ImmutableSet<LinkageProblem> run(String groupId, String artifactId) throws RepositoryException, IOException, MavenRepositoryException, ModelBuildingException {
    String latestBomCoordinates = RepositoryUtility.findLatestCoordinates(repositorySystem, groupId, artifactId);
    logger.info("BOM Coordinates: " + latestBomCoordinates);
    Bom baseline = Bom.readBom(latestBomCoordinates);
    ImmutableSet<LinkageProblem> problemsInBaseline = LinkageChecker.create(baseline, null).findLinkageProblems();
    Bom snapshot = copyWithSnapshot(repositorySystem, session, baseline, localArtifacts);
    // Comparing coordinates because DefaultArtifact does not override equals
    ImmutableList<String> baselineCoordinates = coordinatesList(baseline.getManagedDependencies());
    ImmutableList<String> snapshotCoordinates = coordinatesList(snapshot.getManagedDependencies());
    if (baselineCoordinates.equals(snapshotCoordinates)) {
        logger.info("Snapshot is same as baseline. Not running comparison.");
        logger.info("Baseline coordinates: " + Joiner.on(";").join(baselineCoordinates));
        return ImmutableSet.of();
    }
    ImmutableList<Artifact> snapshotManagedDependencies = snapshot.getManagedDependencies();
    ClassPathResult classPathResult = (new ClassPathBuilder()).resolve(snapshotManagedDependencies, true, DependencyMediation.MAVEN);
    ImmutableList<ClassPathEntry> classpath = classPathResult.getClassPath();
    List<ClassPathEntry> entryPointJars = classpath.subList(0, snapshotManagedDependencies.size());
    ImmutableSet<LinkageProblem> problemsInSnapshot = LinkageChecker.create(classpath, ImmutableSet.copyOf(entryPointJars), null).findLinkageProblems();
    if (problemsInBaseline.equals(problemsInSnapshot)) {
        logger.info("Snapshot versions have the same " + problemsInBaseline.size() + " errors as baseline");
        return ImmutableSet.of();
    }
    Set<LinkageProblem> fixedProblems = Sets.difference(problemsInBaseline, problemsInSnapshot);
    if (!fixedProblems.isEmpty()) {
        logger.info(messageForFixedErrors(fixedProblems));
    }
    Set<LinkageProblem> newProblems = Sets.difference(problemsInSnapshot, problemsInBaseline);
    if (!newProblems.isEmpty()) {
        logger.severe(messageForNewErrors(problemsInSnapshot, problemsInBaseline, classPathResult));
    }
    return ImmutableSet.copyOf(newProblems);
}
Also used : Bom(com.google.cloud.tools.opensource.dependencies.Bom) LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem) ClassPathResult(com.google.cloud.tools.opensource.classpath.ClassPathResult) ClassPathBuilder(com.google.cloud.tools.opensource.classpath.ClassPathBuilder) Artifact(org.eclipse.aether.artifact.Artifact) DefaultArtifact(org.eclipse.aether.artifact.DefaultArtifact) ClassPathEntry(com.google.cloud.tools.opensource.classpath.ClassPathEntry)

Example 8 with ClassPathResult

use of com.google.cloud.tools.opensource.classpath.ClassPathResult 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 9 with ClassPathResult

use of com.google.cloud.tools.opensource.classpath.ClassPathResult in project cloud-opensource-java by GoogleCloudPlatform.

the class LinkageMonitorTest method generateMessageForNewError.

@Test
public void generateMessageForNewError() {
    Set<LinkageProblem> baselineProblems = ImmutableSet.of(classNotFoundProblem);
    ImmutableSet<LinkageProblem> snapshotProblems = ImmutableSet.of(// This is in baseline. It should not be printed
    classNotFoundProblem, methodNotFoundProblemFromA, methodNotFoundProblemFromB);
    DependencyPath pathToA = new DependencyPath(new DefaultArtifact("foo:bar:1.0.0")).append(new org.eclipse.aether.graph.Dependency(new DefaultArtifact("foo:a:1.2.3"), "compile", true));
    DependencyPath pathToB = new DependencyPath(new DefaultArtifact("foo:b:1.0.0"));
    String message = LinkageMonitor.messageForNewErrors(snapshotProblems, baselineProblems, new ClassPathResult(AnnotatedClassPath.fromMultimap(ImmutableListMultimap.of(jarA, pathToA, jarB, pathToB)), ImmutableList.of()));
    assertEquals("Newly introduced problem:\n" + "(foo:b:1.0.0) io.grpc.protobuf.ProtoUtils's method" + " \"io.grpc.MethodDescriptor$Marshaller marshaller(com.google.protobuf.Message)\"" + " is not found\n" + "  referenced from com.abc.AAA (foo:a:1.2.3)\n" + "  referenced from com.abc.BBB (foo:a:1.2.3)\n" + "\n" + "foo:b:1.0.0 is at:\n" + "  foo:b:jar:1.0.0\n" + "foo:a:1.2.3 is at:\n" + "  foo:bar:jar:1.0.0 / foo:a:1.2.3 (compile, optional)\n", message);
}
Also used : LinkageProblem(com.google.cloud.tools.opensource.classpath.LinkageProblem) DependencyPath(com.google.cloud.tools.opensource.dependencies.DependencyPath) ClassPathResult(com.google.cloud.tools.opensource.classpath.ClassPathResult) DefaultArtifact(org.eclipse.aether.artifact.DefaultArtifact) Test(org.junit.Test)

Example 10 with ClassPathResult

use of com.google.cloud.tools.opensource.classpath.ClassPathResult 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)

Aggregations

ClassPathResult (com.google.cloud.tools.opensource.classpath.ClassPathResult)15 Artifact (org.eclipse.aether.artifact.Artifact)12 ClassPathEntry (com.google.cloud.tools.opensource.classpath.ClassPathEntry)11 AnnotatedClassPath (com.google.cloud.tools.opensource.classpath.AnnotatedClassPath)8 ClassPathBuilder (com.google.cloud.tools.opensource.classpath.ClassPathBuilder)8 DependencyPath (com.google.cloud.tools.opensource.dependencies.DependencyPath)8 DefaultArtifact (org.eclipse.aether.artifact.DefaultArtifact)8 LinkageProblem (com.google.cloud.tools.opensource.classpath.LinkageProblem)6 Path (java.nio.file.Path)6 DependencyGraph (com.google.cloud.tools.opensource.dependencies.DependencyGraph)5 ImmutableList (com.google.common.collect.ImmutableList)5 LinkageChecker (com.google.cloud.tools.opensource.classpath.LinkageChecker)4 Dependency (org.eclipse.aether.graph.Dependency)4 Bom (com.google.cloud.tools.opensource.dependencies.Bom)3 DependencyGraphBuilder (com.google.cloud.tools.opensource.dependencies.DependencyGraphBuilder)3 Configuration (freemarker.template.Configuration)3 HashMap (java.util.HashMap)3 EnforcerRuleException (org.apache.maven.enforcer.rule.api.EnforcerRuleException)3 Test (org.junit.Test)3 ClassReferenceGraph (com.google.cloud.tools.opensource.classpath.ClassReferenceGraph)2