Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding support for 'pom' packaging #65

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
package com.societegenerale.commons.plugin.maven;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.societegenerale.commons.plugin.Log;
import com.societegenerale.commons.plugin.maven.model.MavenRules;
import com.societegenerale.commons.plugin.model.Rules;
Expand All @@ -23,6 +15,15 @@
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.net.URLClassLoader.newInstance;
import static java.util.Collections.emptyList;

Expand Down Expand Up @@ -80,55 +81,84 @@ public void execute() throws MojoFailureException {
return;
}

Rules coreRules=rules.toCoreRules();

if (!coreRules.isValid()) {
if (!rules.toCoreRules().isValid()) {
throw new MojoFailureException("Arch unit Plugin should have at least one preconfigured/configurable rule");
}

String ruleFailureMessage;

Rules coreRules;
List<MavenProject> targetProjects;
if ("pom".equals(mavenProject.getPackaging())) {
getLog().debug("module packaging is 'pom', so skipping execution");
return;
coreRules = rules.toCoreRules(true);
targetProjects = mavenProject.getCollectedProjects();
}
else {
coreRules = rules.toCoreRules(false);
targetProjects = List.of(mavenProject);
}

if (!properties.isEmpty()) {
getLog().debug("configuring ArchUnit properties");
final ArchConfiguration archConfiguration = ArchConfiguration.get();
properties.forEach(archConfiguration::setProperty);
ruleFailureMessage = executeArchUnitRules(coreRules, targetProjects);

if (!StringUtils.isEmpty(ruleFailureMessage)) {
if(!noFailOnError) {
throw new MojoFailureException(PREFIX_ARCH_VIOLATION_MESSAGE + ruleFailureMessage);
}

getLog().info(PREFIX_ARCH_VIOLATION_MESSAGE + ruleFailureMessage);
}
}

String ruleFailureMessage;
private String executeArchUnitRules(Rules coreRules, List<MavenProject> projects) throws MojoFailureException {
if (!coreRules.isValid()) {
String debugMessage = "no rule apply for projects";
if (!projects.isEmpty()) {
debugMessage += ": %s".formatted(projects.stream()
.map(MavenProject::getName)
.collect(Collectors.joining(";")));
}
getLog().debug(debugMessage);
return null;
}
configureProperties();
try {
configureContextClassLoader();
configureContextClassLoader(projects);
final Log mavenLogAdapter = new MavenLogAdapter(getLog());

ruleInvokerService = new RuleInvokerService(mavenLogAdapter, new MavenScopePathProvider(mavenProject), excludedPaths, projectBuildDir);
ruleInvokerService = new RuleInvokerService(mavenLogAdapter,
projects.stream().map(MavenScopePathProvider::new).collect(Collectors.toList()),
excludedPaths,
projectBuildDir);

ruleFailureMessage = ruleInvokerService.invokeRules(coreRules);
return ruleInvokerService.invokeRules(coreRules);
} catch (final Exception e) {
throw new MojoFailureException(e.getMessage(), e);
}
}

if (!StringUtils.isEmpty(ruleFailureMessage)) {
if(!noFailOnError) {
throw new MojoFailureException(PREFIX_ARCH_VIOLATION_MESSAGE + ruleFailureMessage);
}

getLog().warn(PREFIX_ARCH_VIOLATION_MESSAGE + ruleFailureMessage);
private void configureProperties() {
if (!properties.isEmpty()) {
getLog().debug("configuring ArchUnit properties");
final ArchConfiguration archConfiguration = ArchConfiguration.get();
properties.forEach(archConfiguration::setProperty);
}
}

private void configureContextClassLoader() throws DependencyResolutionRequiredException, MalformedURLException {
private void configureContextClassLoader(List<MavenProject> projects)
throws DependencyResolutionRequiredException, MalformedURLException {

List<URL> urls = new ArrayList<>();
List<String> elements = mavenProject.getTestClasspathElements();
for (String element : elements) {
urls.add(new File(element).toURI().toURL());
for (MavenProject project : projects) {
for (String element : project.getTestClasspathElements()) {
urls.add(new File(element).toURI().toURL());
}
}

ClassLoader contextClassLoader = newInstance(urls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader());
ClassLoader contextClassLoader = newInstance(urls.toArray(new URL[0]),
Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(contextClassLoader);
}

void setProjectBuildDir(final String projectBuildDir) {
this.projectBuildDir = projectBuildDir;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@ public class MavenApplyOn {
@Parameter(property = "scope")
private String scope;

@Parameter(property = "aggregator", defaultValue = "false")
private boolean aggregator;

//default constructor is required at runtime
public MavenApplyOn() {

}

//convenience constructor when calling from unit tests
public MavenApplyOn(String packageName, String scope) {
public MavenApplyOn(String packageName, String scope, boolean aggregator) {
this.packageName = packageName;
this.scope = scope;
this.aggregator = aggregator;
}

public String getPackageName() {
Expand All @@ -30,6 +34,10 @@ public String getScope() {
return scope;
}

public boolean getAggregator() {
return aggregator;
}

public void setPackageName(String packageName) {
this.packageName = packageName;
}
Expand All @@ -38,7 +46,11 @@ public void setScope(String scope) {
this.scope = scope;
}

public void setAggregator(boolean aggregator) {
this.aggregator = aggregator;
}

public ApplyOn toCoreApplyOn() {
return new ApplyOn(packageName,scope);
return new ApplyOn(packageName,scope);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import com.societegenerale.commons.plugin.model.Rules;
import org.apache.maven.plugins.annotations.Parameter;
Expand Down Expand Up @@ -29,8 +30,16 @@ public Rules toCoreRules(){

return new Rules(preConfiguredRules,
configurableRules.stream()
.map(e -> e.toCoreConfigurableRule())
.collect(toList()));
.map(e -> e.toCoreConfigurableRule())
.collect(toList()));
}

public Rules toCoreRules(boolean isApplyOnAggregator) {
return new Rules(isApplyOnAggregator ? List.of() : preConfiguredRules,
configurableRules.stream()
.filter(configurableRule -> Optional.ofNullable(configurableRule.getApplyOn()).map(MavenApplyOn::getAggregator).orElse(false) == isApplyOnAggregator)
.map(MavenConfigurableRule::toCoreConfigurableRule)
.toList());
}

public List<String> getPreConfiguredRules() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,82 +17,90 @@
abstract class AbstractArchUnitMojoTest
{
protected static ExpectedRuleFailure.Creator expectRuleFailure(String ruleDescription) {
return new ExpectedRuleFailure.Creator(ruleDescription);
return new ExpectedRuleFailure.Creator(ruleDescription);
}

protected String getBasedir() {
String basedir = System.getProperty("basedir");
String basedir = System.getProperty("basedir");

if (basedir == null) {
basedir = new File("").getAbsolutePath();
}
if (basedir == null) {
basedir = new File("").getAbsolutePath();
}

return basedir;
return basedir;
}

protected void executeAndExpectViolations(ArchUnitMojo mojo, ExpectedRuleFailure... expectedRuleFailures) {
AbstractThrowableAssert<?, ? extends Throwable> throwableAssert = assertThatThrownBy(mojo::execute);
stream(expectedRuleFailures).forEach(expectedFailure -> {
throwableAssert.hasMessageContaining(String.format("Rule '%s' was violated", expectedFailure.ruleDescription));
expectedFailure.details.forEach(throwableAssert::hasMessageContaining);
});
throwableAssert.has(exactNumberOfViolatedRules(expectedRuleFailures.length));
AbstractThrowableAssert<?, ? extends Throwable> throwableAssert = assertThatThrownBy(mojo::execute);
stream(expectedRuleFailures).forEach(expectedFailure -> {
throwableAssert.hasMessageContaining(String.format("Rule '%s' was violated", expectedFailure.ruleDescription));
expectedFailure.details.forEach(throwableAssert::hasMessageContaining);
});
throwableAssert.has(exactNumberOfViolatedRules(expectedRuleFailures.length));
}

private Condition<Throwable> exactNumberOfViolatedRules(final int number) {
return new Condition<Throwable>("exactly " + number + " violated rules") {
@Override
public boolean matches(Throwable throwable) {
Matcher matcher = Pattern.compile("Rule '.*' was violated").matcher(throwable.getMessage());
int numberOfOccurrences = 0;
while (matcher.find()) {
numberOfOccurrences++;
}
return numberOfOccurrences == number;
}
};
return new Condition<Throwable>("exactly " + number + " violated rules") {
@Override
public boolean matches(Throwable throwable) {
Matcher matcher = Pattern.compile("Rule '.*' was violated").matcher(throwable.getMessage());
int numberOfOccurrences = 0;
while (matcher.find()) {
numberOfOccurrences++;
}
return numberOfOccurrences == number;
}
};
}

protected PlexusConfiguration buildApplyOnBlock(String packageName, String scope) {

PlexusConfiguration packageNameElement = new DefaultPlexusConfiguration("packageName", packageName);
PlexusConfiguration scopeElement = new DefaultPlexusConfiguration("scope", scope);
PlexusConfiguration applyOnElement = new DefaultPlexusConfiguration("applyOn");
applyOnElement.addChild(packageNameElement);
applyOnElement.addChild(scopeElement);
return buildApplyOnBlock(packageName, scope, false);
}

protected PlexusConfiguration buildApplyOnBlock(String packageName, String scope, Boolean aggregator) {

PlexusConfiguration packageNameElement = new DefaultPlexusConfiguration("packageName", packageName);
PlexusConfiguration scopeElement = new DefaultPlexusConfiguration("scope", scope);
PlexusConfiguration aggregatorElement = new DefaultPlexusConfiguration("aggregator", aggregator.toString());
PlexusConfiguration applyOnElement = new DefaultPlexusConfiguration("applyOn");
applyOnElement.addChild(packageNameElement);
applyOnElement.addChild(scopeElement);
applyOnElement.addChild(aggregatorElement);

return applyOnElement;
return applyOnElement;
}


protected PlexusConfiguration buildChecksBlock(String... checks) {
PlexusConfiguration checksElement = new DefaultPlexusConfiguration("checks");
stream(checks).map(c -> new DefaultPlexusConfiguration("check", c)).forEach(checksElement::addChild);
return checksElement;
PlexusConfiguration checksElement = new DefaultPlexusConfiguration("checks");
stream(checks).map(c -> new DefaultPlexusConfiguration("check", c)).forEach(checksElement::addChild);
return checksElement;
}

public static class ExpectedRuleFailure {
private final String ruleDescription;
private final Set<String> details;

private ExpectedRuleFailure(String ruleDescription, Set<String> details) {
this.ruleDescription = ruleDescription;
this.details = details;
}

public static class Creator {
private final String ruleDescription;
private final Set<String> details;

Creator(String ruleDescription) {
this.ruleDescription = ruleDescription;
private ExpectedRuleFailure(String ruleDescription, Set<String> details) {
this.ruleDescription = ruleDescription;
this.details = details;
}

ExpectedRuleFailure ofAnyKind() {
return withDetails();
}
public static class Creator {
private final String ruleDescription;

Creator(String ruleDescription) {
this.ruleDescription = ruleDescription;
}

ExpectedRuleFailure ofAnyKind() {
return withDetails();
}

ExpectedRuleFailure withDetails(String... detals) {
return new ExpectedRuleFailure(ruleDescription, ImmutableSet.copyOf(detals));
ExpectedRuleFailure withDetails(String... detals) {
return new ExpectedRuleFailure(ruleDescription, ImmutableSet.copyOf(detals));
}
}
}
}
}
Loading