
de.is24.deadcode4j.plugin.ModuleGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of deadcode4j-maven-plugin Show documentation
Show all versions of deadcode4j-maven-plugin Show documentation
Finds unused classes of a project
package de.is24.deadcode4j.plugin;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.cache.LoadingCache;
import de.is24.deadcode4j.Module;
import de.is24.deadcode4j.Repository;
import de.is24.deadcode4j.Resource;
import de.is24.deadcode4j.plugin.packaginghandler.DefaultPackagingHandler;
import de.is24.deadcode4j.plugin.packaginghandler.PackagingHandler;
import de.is24.deadcode4j.plugin.packaginghandler.PomPackagingHandler;
import de.is24.deadcode4j.plugin.packaginghandler.WarPackagingHandler;
import de.is24.guava.NonNullFunction;
import de.is24.guava.NonNullFunctions;
import de.is24.guava.SequentialLoadingCache;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.RepositorySystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static com.google.common.base.Optional.absent;
import static com.google.common.base.Optional.of;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static de.is24.deadcode4j.Utils.*;
/**
* Calculates the modules for the given maven projects.
*
* @see #getModulesFor(Iterable)
* @since 2.0.0
*/
@SuppressWarnings("PMD.TooManyStaticImports")
class ModuleGenerator {
@Nonnull
private final Logger logger = LoggerFactory.getLogger(getClass());
@Nonnull
private final PackagingHandler defaultPackagingHandler = new DefaultPackagingHandler();
@Nonnull
private final Map packagingHandlers = newHashMap();
@Nonnull
private final LoadingCache> artifactResolverCache;
/**
* Creates a new ModuleGenerator
.
*
* @param repositorySystem the given RepositorySystem
is required to resolve the class path of the
* examined maven projects
* @since 2.0.0
*/
public ModuleGenerator(@Nonnull final RepositorySystem repositorySystem) {
packagingHandlers.put("pom", new PomPackagingHandler());
packagingHandlers.put("war", new WarPackagingHandler());
artifactResolverCache = new SequentialLoadingCache(NonNullFunctions.toFunction(new NonNullFunction>() {
@Nonnull
@Override
public Optional apply(@Nonnull Artifact input) {
if (!input.isResolved()) {
ArtifactResolutionRequest request = new ArtifactResolutionRequest();
request.setResolveRoot(true);
request.setResolveTransitively(false);
request.setArtifact(input);
ArtifactResolutionResult artifactResolutionResult = repositorySystem.resolve(request);
if (!artifactResolutionResult.isSuccess()) {
logger.warn(" Failed to resolve [{}]; some analyzers may not work properly.", getVersionedKeyFor(input));
return absent();
}
}
File classPathElement = input.getFile();
if (classPathElement == null) {
logger.warn(" No valid path to [{}] found; some analyzers may not work properly.", getVersionedKeyFor(input));
return absent();
}
return of(classPathElement);
}
}));
}
/**
* Attempts to create a Module
for each given maven project. A project providing no repository will be
* silently ignored.
*
* @param projects the MavenProject
s to transform; the projects MUST be ordered such that project
* A is listed before project B if B depends on A
* @throws MojoExecutionException if calculating the repositories fails
* @since 2.0.0
*/
@Nonnull
public Iterable getModulesFor(@Nonnull Iterable projects) throws MojoExecutionException {
Map knownModules = newHashMap();
for (MavenProject project : projects) {
Module module = getModuleFor(project, knownModules);
knownModules.put(module.getModuleId(), module);
logger.debug("Added [{}] for [{}].", module, project);
}
return knownModules.values();
}
@Nonnull
private Module getModuleFor(
@Nonnull MavenProject project,
@Nonnull Map knownModules) throws MojoExecutionException {
String projectId = getKeyFor(project);
String encoding = nullIfEmpty(project.getProperties().getProperty("project.build.sourceEncoding"));
if (encoding == null) {
logger.warn("No encoding set for [{}]! Parsing source files may cause issues.", projectId);
}
PackagingHandler packagingHandler =
getValueOrDefault(this.packagingHandlers, project.getPackaging(), this.defaultPackagingHandler);
Repository outputRepository = packagingHandler.getOutputRepositoryFor(project);
Iterable additionalRepositories = packagingHandler.getAdditionalRepositoriesFor(project);
Collection dependencies = computeDependencies(project, knownModules);
return new Module(projectId, encoding, dependencies, outputRepository, additionalRepositories);
}
@Nonnull
protected Collection computeDependencies(
@Nonnull MavenProject project,
@Nonnull Map knownModules) {
logger.debug("Gathering dependencies for project [{}]...", getKeyFor(project));
List dependencies = newArrayList();
for (Artifact dependency : filter(project.getArtifacts(), artifactsWithCompileScope())) {
if (addKnownArtifact(dependencies, dependency, knownModules)) {
continue;
}
final Optional artifactPath = this.artifactResolverCache.getUnchecked(dependency);
if (artifactPath.isPresent()) {
final File classPathElement = artifactPath.get();
dependencies.add(Resource.of(classPathElement));
logger.debug(" Added artifact: [{}]", classPathElement);
}
}
logger.debug("[{}] dependencies found for [{}].", dependencies.size(), getKeyFor(project));
return dependencies;
}
private Predicate artifactsWithCompileScope() {
return new Predicate() {
private ScopeArtifactFilter artifactFilter = new ScopeArtifactFilter(Artifact.SCOPE_COMPILE);
@Override
public boolean apply(@Nullable Artifact input) {
return input != null && artifactFilter.include(input);
}
};
}
private boolean addKnownArtifact(
@Nonnull List resources,
@Nonnull Artifact artifact,
@Nonnull Map knownModules) {
String dependencyKey = getKeyFor(artifact);
Module knownModule = knownModules.get(dependencyKey);
if (knownModule == null) {
return false;
}
resources.add(Resource.of(knownModule));
logger.debug(" Added project: [{}]", knownModule);
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy