diff --git a/pom.xml b/pom.xml index cd202f517..65c7e2b58 100644 --- a/pom.xml +++ b/pom.xml @@ -90,15 +90,9 @@ 1.11 - org.reflections - reflections - 0.10.2 - - - com.google.code.findbugs - jsr305 - - + org.kohsuke.metainf-services + metainf-services + 1.9 org.slf4j @@ -192,23 +186,6 @@ - - org.apache.maven.plugins - maven-compiler-plugin - - - - - info.picocli - picocli-codegen - ${picocli.version} - - - - -Aproject=${project.groupId}/${project.artifactId} - - - org.jenkins-ci.tools maven-hpi-plugin diff --git a/src/main/java/org/jenkins/tools/test/PluginCompatTester.java b/src/main/java/org/jenkins/tools/test/PluginCompatTester.java index 85d495234..a26a29364 100644 --- a/src/main/java/org/jenkins/tools/test/PluginCompatTester.java +++ b/src/main/java/org/jenkins/tools/test/PluginCompatTester.java @@ -96,9 +96,7 @@ public PluginCompatTester(PluginCompatTesterConfig config) { public void testPlugins() throws PluginCompatibilityTesterException { PluginCompatTesterHooks pcth = new PluginCompatTesterHooks( - config.getHookPrefixes(), - config.getExternalHooksJars(), - config.getExcludeHooks()); + config.getExternalHooksJars(), config.getExcludeHooks()); // Determine the plugin data // Scan bundled plugins. If there is any bundled plugin, only these plugins will be taken diff --git a/src/main/java/org/jenkins/tools/test/PluginCompatTesterCli.java b/src/main/java/org/jenkins/tools/test/PluginCompatTesterCli.java index ea9c90e0b..824052833 100644 --- a/src/main/java/org/jenkins/tools/test/PluginCompatTesterCli.java +++ b/src/main/java/org/jenkins/tools/test/PluginCompatTesterCli.java @@ -130,15 +130,6 @@ public class PluginCompatTesterCli implements Callable { "Comma-separated list of arguments to pass to Maven (like -Pxxx; not to be confused with Java arguments or Maven properties). These arguments will be passed to Maven both during compilation and when running tests.") private List mavenArgs; - @CheckForNull - @CommandLine.Option( - names = "--hook-prefixes", - split = ",", - arity = "1", - paramLabel = "prefix", - description = "Comma-separated list of prefixes of extra hook classes.") - private List hookPrefixes; - @CheckForNull @CommandLine.Option( names = "--external-hooks-jars", @@ -189,9 +180,6 @@ public Integer call() throws PluginCompatibilityTesterException { if (mavenArgs != null) { config.setMavenArgs(mavenArgs); } - if (hookPrefixes != null) { - config.setHookPrefixes(hookPrefixes); - } if (externalHooksJars != null) { config.setExternalHooksJars(externalHooksJars); } diff --git a/src/main/java/org/jenkins/tools/test/hook/AnalysisPomExecutionHook.java b/src/main/java/org/jenkins/tools/test/hook/AnalysisPomExecutionHook.java index 142a10f05..a668b7068 100644 --- a/src/main/java/org/jenkins/tools/test/hook/AnalysisPomExecutionHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/AnalysisPomExecutionHook.java @@ -4,11 +4,14 @@ import java.util.Set; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeExecutionContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeExecution; +import org.kohsuke.MetaInfServices; /** * Custom execution hook for plugins whose parent is {@code org.jvnet.hudson.plugins:analysis-pom}. * These plugins use Maven Failsafe Plugin in their test suites. */ +@MetaInfServices(PluginCompatTesterHookBeforeExecution.class) public class AnalysisPomExecutionHook extends PluginWithFailsafeIntegrationTestsHook { private static final Set ARTIFACT_IDS = diff --git a/src/main/java/org/jenkins/tools/test/hook/AwsJavaSdkHook.java b/src/main/java/org/jenkins/tools/test/hook/AwsJavaSdkHook.java index e049d1717..71bd71df6 100644 --- a/src/main/java/org/jenkins/tools/test/hook/AwsJavaSdkHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/AwsJavaSdkHook.java @@ -3,7 +3,10 @@ import edu.umd.cs.findbugs.annotations.NonNull; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeCheckoutContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeCheckout; +import org.kohsuke.MetaInfServices; +@MetaInfServices(PluginCompatTesterHookBeforeCheckout.class) public class AwsJavaSdkHook extends AbstractMultiParentHook { @Override diff --git a/src/main/java/org/jenkins/tools/test/hook/BlueOceanHook.java b/src/main/java/org/jenkins/tools/test/hook/BlueOceanHook.java index 6ad6c83fc..7eacc8cab 100644 --- a/src/main/java/org/jenkins/tools/test/hook/BlueOceanHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/BlueOceanHook.java @@ -3,8 +3,11 @@ import edu.umd.cs.findbugs.annotations.NonNull; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeCheckoutContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeCheckout; +import org.kohsuke.MetaInfServices; /** Workaround for the Blue Ocean plugins since they are stored in a central repository. */ +@MetaInfServices(PluginCompatTesterHookBeforeCheckout.class) public class BlueOceanHook extends AbstractMultiParentHook { @Override diff --git a/src/main/java/org/jenkins/tools/test/hook/ConfigurationAsCodeHook.java b/src/main/java/org/jenkins/tools/test/hook/ConfigurationAsCodeHook.java index 1845f580e..40564bd78 100644 --- a/src/main/java/org/jenkins/tools/test/hook/ConfigurationAsCodeHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/ConfigurationAsCodeHook.java @@ -3,7 +3,10 @@ import edu.umd.cs.findbugs.annotations.NonNull; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeCheckoutContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeCheckout; +import org.kohsuke.MetaInfServices; +@MetaInfServices(PluginCompatTesterHookBeforeCheckout.class) public class ConfigurationAsCodeHook extends AbstractMultiParentHook { @Override diff --git a/src/main/java/org/jenkins/tools/test/hook/DeclarativePipelineHook.java b/src/main/java/org/jenkins/tools/test/hook/DeclarativePipelineHook.java index 0c3eaf389..dfc2b67f5 100644 --- a/src/main/java/org/jenkins/tools/test/hook/DeclarativePipelineHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/DeclarativePipelineHook.java @@ -4,10 +4,13 @@ import java.util.Set; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeCheckoutContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeCheckout; +import org.kohsuke.MetaInfServices; /** * Workaround for the Pipeline: Declarative plugins since they are stored in a central repository. */ +@MetaInfServices(PluginCompatTesterHookBeforeCheckout.class) public class DeclarativePipelineHook extends AbstractMultiParentHook { private static final Set ARTIFACT_IDS = diff --git a/src/main/java/org/jenkins/tools/test/hook/DeclarativePipelineMigrationHook.java b/src/main/java/org/jenkins/tools/test/hook/DeclarativePipelineMigrationHook.java index 52017e56d..4bf63ac6c 100644 --- a/src/main/java/org/jenkins/tools/test/hook/DeclarativePipelineMigrationHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/DeclarativePipelineMigrationHook.java @@ -4,11 +4,14 @@ import java.util.Set; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeCheckoutContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeCheckout; +import org.kohsuke.MetaInfServices; /** * Workaround for the Declarative Pipeline Migration Assistant plugins since they are stored in a * central repository. */ +@MetaInfServices(PluginCompatTesterHookBeforeCheckout.class) public class DeclarativePipelineMigrationHook extends AbstractMultiParentHook { private static final Set ARTIFACT_IDS = diff --git a/src/main/java/org/jenkins/tools/test/hook/HpiPluginHook.java b/src/main/java/org/jenkins/tools/test/hook/HpiPluginHook.java index 957f50d91..d34d5efad 100644 --- a/src/main/java/org/jenkins/tools/test/hook/HpiPluginHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/HpiPluginHook.java @@ -16,6 +16,7 @@ import org.jenkins.tools.test.model.PluginCompatTesterConfig; import org.jenkins.tools.test.model.hook.BeforeExecutionContext; import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeExecution; +import org.kohsuke.MetaInfServices; /** * The {@code overrideWar} option is available in HPI Plugin 3.29 or later, but many plugins under @@ -24,6 +25,7 @@ * the managed set are using a plugin parent POM with HPI Plugin 3.29 or later (i.e., plugin parent * POM 4.44 or later), this can be deleted. */ +@MetaInfServices(PluginCompatTesterHookBeforeExecution.class) public class HpiPluginHook extends PluginCompatTesterHookBeforeExecution { @Override diff --git a/src/main/java/org/jenkins/tools/test/hook/JacocoHook.java b/src/main/java/org/jenkins/tools/test/hook/JacocoHook.java index b096fd0e0..1ed537aa6 100644 --- a/src/main/java/org/jenkins/tools/test/hook/JacocoHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/JacocoHook.java @@ -6,11 +6,13 @@ import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeExecutionContext; import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeExecution; +import org.kohsuke.MetaInfServices; /** * Workaround for JaCoCo plugin since it needs execute the jacoco:prepare-agent goal before * execution. */ +@MetaInfServices(PluginCompatTesterHookBeforeExecution.class) public class JacocoHook extends PluginCompatTesterHookBeforeExecution { @Override diff --git a/src/main/java/org/jenkins/tools/test/hook/MinaSshdApi.java b/src/main/java/org/jenkins/tools/test/hook/MinaSshdApi.java index 34671c6e0..744e2c441 100644 --- a/src/main/java/org/jenkins/tools/test/hook/MinaSshdApi.java +++ b/src/main/java/org/jenkins/tools/test/hook/MinaSshdApi.java @@ -3,7 +3,10 @@ import edu.umd.cs.findbugs.annotations.NonNull; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeCheckoutContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeCheckout; +import org.kohsuke.MetaInfServices; +@MetaInfServices(PluginCompatTesterHookBeforeCheckout.class) public class MinaSshdApi extends AbstractMultiParentHook { @Override diff --git a/src/main/java/org/jenkins/tools/test/hook/MultiParentCompileHook.java b/src/main/java/org/jenkins/tools/test/hook/MultiParentCompileHook.java index 9cc969385..6a952ef62 100644 --- a/src/main/java/org/jenkins/tools/test/hook/MultiParentCompileHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/MultiParentCompileHook.java @@ -27,7 +27,9 @@ import org.jenkins.tools.test.model.hook.PluginCompatTesterHooks; import org.jenkins.tools.test.model.hook.Stage; import org.jenkins.tools.test.model.hook.StageContext; +import org.kohsuke.MetaInfServices; +@MetaInfServices(PluginCompatTesterHookBeforeCompile.class) @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "intended behavior") public class MultiParentCompileHook extends PluginCompatTesterHookBeforeCompile { diff --git a/src/main/java/org/jenkins/tools/test/hook/PipelineStageViewHook.java b/src/main/java/org/jenkins/tools/test/hook/PipelineStageViewHook.java index cbcb816d5..11cac493e 100644 --- a/src/main/java/org/jenkins/tools/test/hook/PipelineStageViewHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/PipelineStageViewHook.java @@ -4,7 +4,10 @@ import java.util.Set; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeCheckoutContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeCheckout; +import org.kohsuke.MetaInfServices; +@MetaInfServices(PluginCompatTesterHookBeforeCheckout.class) public class PipelineStageViewHook extends AbstractMultiParentHook { private static final Set ARTIFACT_IDS = diff --git a/src/main/java/org/jenkins/tools/test/hook/SwarmHook.java b/src/main/java/org/jenkins/tools/test/hook/SwarmHook.java index 3e3d7b646..e51d06c7e 100644 --- a/src/main/java/org/jenkins/tools/test/hook/SwarmHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/SwarmHook.java @@ -3,7 +3,10 @@ import edu.umd.cs.findbugs.annotations.NonNull; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeCheckoutContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeCheckout; +import org.kohsuke.MetaInfServices; +@MetaInfServices(PluginCompatTesterHookBeforeCheckout.class) public class SwarmHook extends AbstractMultiParentHook { @Override diff --git a/src/main/java/org/jenkins/tools/test/hook/WarningsNGCheckoutHook.java b/src/main/java/org/jenkins/tools/test/hook/WarningsNGCheckoutHook.java index 5d626f0b3..3bfaccf3f 100644 --- a/src/main/java/org/jenkins/tools/test/hook/WarningsNGCheckoutHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/WarningsNGCheckoutHook.java @@ -6,7 +6,10 @@ import java.util.logging.Logger; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeCheckoutContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeCheckout; +import org.kohsuke.MetaInfServices; +@MetaInfServices(PluginCompatTesterHookBeforeCheckout.class) public class WarningsNGCheckoutHook extends AbstractMultiParentHook { private static final Logger LOGGER = Logger.getLogger(WarningsNGCheckoutHook.class.getName()); diff --git a/src/main/java/org/jenkins/tools/test/hook/WarningsNGExecutionHook.java b/src/main/java/org/jenkins/tools/test/hook/WarningsNGExecutionHook.java index 9b7c6cab8..a36e11eea 100644 --- a/src/main/java/org/jenkins/tools/test/hook/WarningsNGExecutionHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/WarningsNGExecutionHook.java @@ -3,8 +3,11 @@ import edu.umd.cs.findbugs.annotations.NonNull; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeExecutionContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeExecution; +import org.kohsuke.MetaInfServices; /** Workaround for Warnings NG plugin since it needs execute integration tests. */ +@MetaInfServices(PluginCompatTesterHookBeforeExecution.class) public class WarningsNGExecutionHook extends PluginWithFailsafeIntegrationTestsHook { @Override diff --git a/src/main/java/org/jenkins/tools/test/hook/WorkflowCpsHook.java b/src/main/java/org/jenkins/tools/test/hook/WorkflowCpsHook.java index ebaa8b0a7..abbbd9631 100644 --- a/src/main/java/org/jenkins/tools/test/hook/WorkflowCpsHook.java +++ b/src/main/java/org/jenkins/tools/test/hook/WorkflowCpsHook.java @@ -4,7 +4,10 @@ import hudson.util.VersionNumber; import org.apache.maven.model.Model; import org.jenkins.tools.test.model.hook.BeforeCheckoutContext; +import org.jenkins.tools.test.model.hook.PluginCompatTesterHookBeforeCheckout; +import org.kohsuke.MetaInfServices; +@MetaInfServices(PluginCompatTesterHookBeforeCheckout.class) public class WorkflowCpsHook extends AbstractMultiParentHook { @Override diff --git a/src/main/java/org/jenkins/tools/test/model/PluginCompatTesterConfig.java b/src/main/java/org/jenkins/tools/test/model/PluginCompatTesterConfig.java index 3dfeb6bcd..e1cee704b 100644 --- a/src/main/java/org/jenkins/tools/test/model/PluginCompatTesterConfig.java +++ b/src/main/java/org/jenkins/tools/test/model/PluginCompatTesterConfig.java @@ -29,7 +29,6 @@ import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import java.io.File; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -73,9 +72,6 @@ public class PluginCompatTesterConfig { @NonNull private List mavenArgs = List.of(); - // Classpath prefixes of the extra hooks - @NonNull private List hookPrefixes = List.of("org.jenkins"); - // External hooks jar files path locations @NonNull private List externalHooksJars = List.of(); @@ -173,19 +169,6 @@ public void setMavenArgs(@NonNull List mavenArgs) { this.mavenArgs = List.copyOf(mavenArgs); } - @NonNull - public List getHookPrefixes() { - return hookPrefixes; - } - - public void setHookPrefixes(@NonNull List hookPrefixes) { - // Want to also process the default - List combined = new ArrayList<>(); - combined.addAll(this.hookPrefixes); - combined.addAll(hookPrefixes); - this.hookPrefixes = List.copyOf(combined); - } - @NonNull public List getExternalHooksJars() { return externalHooksJars; diff --git a/src/main/java/org/jenkins/tools/test/model/hook/PluginCompatTesterHooks.java b/src/main/java/org/jenkins/tools/test/model/hook/PluginCompatTesterHooks.java index eedd6a882..b5d450350 100644 --- a/src/main/java/org/jenkins/tools/test/model/hook/PluginCompatTesterHooks.java +++ b/src/main/java/org/jenkins/tools/test/model/hook/PluginCompatTesterHooks.java @@ -3,8 +3,6 @@ import edu.umd.cs.findbugs.annotations.NonNull; import java.io.File; import java.io.UncheckedIOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; @@ -13,16 +11,10 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; -import java.util.NavigableSet; -import java.util.Set; -import java.util.TreeSet; -import java.util.function.Supplier; +import java.util.ServiceLoader; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.Collectors; import org.jenkins.tools.test.exception.PluginCompatibilityTesterException; -import org.reflections.Reflections; -import org.reflections.util.ConfigurationBuilder; /** * Loads and executes hooks for modifying the state of Plugin Compatibility Tester at different @@ -37,27 +29,22 @@ public class PluginCompatTesterHooks { private ClassLoader classLoader = PluginCompatTesterHooks.class.getClassLoader(); - @NonNull private final List hookPrefixes; - public static final Map>> hooksByStage = new EnumMap<>(Stage.class); @NonNull private final List excludeHooks; public PluginCompatTesterHooks( - @NonNull List extraPrefixes, - @NonNull List externalJars, - @NonNull List excludeHooks) { - this.hookPrefixes = extraPrefixes; + @NonNull List externalJars, @NonNull List excludeHooks) { this.excludeHooks = excludeHooks; setupExternalClassLoaders(externalJars); setupHooksByStage(); } private void setupHooksByStage() { - for (Stage stage : Stage.values()) { - hooksByStage.put(stage, findHooks(stage)); - } + hooksByStage.put(Stage.CHECKOUT, findHooks(PluginCompatTesterHookBeforeCheckout.class)); + hooksByStage.put(Stage.COMPILATION, findHooks(PluginCompatTesterHookBeforeCompile.class)); + hooksByStage.put(Stage.EXECUTION, findHooks(PluginCompatTesterHookBeforeExecution.class)); } private void setupExternalClassLoaders(List externalJars) { @@ -107,80 +94,14 @@ private void runHooks(@NonNull StageContext context) throws PluginCompatibilityT } } - private List> findHooks(Stage stage) { + private List> findHooks( + Class> clazz) { List> sortedHooks = new ArrayList<>(); - - // Search for all hooks defined within the given classpath prefix - ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); - configurationBuilder.addClassLoaders(classLoader); - for (String hookPrefix : hookPrefixes) { - configurationBuilder.forPackage(hookPrefix, classLoader); - } - Reflections reflections = new Reflections(configurationBuilder); - NavigableSet>> subTypes; - - // Find all steps for a given stage. Long due to casting - switch (stage) { - case COMPILATION: - Set> compSteps = - reflections.getSubTypesOf(PluginCompatTesterHookBeforeCompile.class); - subTypes = - compSteps.stream() - .map(this::casting) - .filter(c -> !Modifier.isAbstract(c.getModifiers())) - .collect(Collectors.toCollection(navigableSet())); - break; - case EXECUTION: - Set> exeSteps = - reflections.getSubTypesOf(PluginCompatTesterHookBeforeExecution.class); - subTypes = - exeSteps.stream() - .map(this::casting) - .filter(c -> !Modifier.isAbstract(c.getModifiers())) - .collect(Collectors.toCollection(navigableSet())); - break; - case CHECKOUT: - Set> checkSteps = - reflections.getSubTypesOf(PluginCompatTesterHookBeforeCheckout.class); - subTypes = - checkSteps.stream() - .map(this::casting) - .filter(c -> !Modifier.isAbstract(c.getModifiers())) - .collect(Collectors.toCollection(navigableSet())); - break; - default: // Not valid; nothing will get executed - throw new IllegalArgumentException("Invalid stage: " + stage); - } - - for (Class> c : subTypes) { - try { - LOGGER.log(Level.FINE, "Loading hook: {0}", c.getName()); - Constructor> constructor = - c.getConstructor(); - PluginCompatTesterHook hook = - (PluginCompatTesterHook) constructor.newInstance(); - sortedHooks.add(hook); - } catch (ReflectiveOperationException e) { - throw new RuntimeException("Error when loading " + c.getName(), e); - } + for (PluginCompatTesterHook hook : + ServiceLoader.load(clazz, classLoader)) { + sortedHooks.add((PluginCompatTesterHook) hook); } - + sortedHooks.sort(Comparator.comparing(hook -> hook.getClass().getName())); return sortedHooks; } - - private static Supplier< - NavigableSet>>> - navigableSet() { - return () -> new TreeSet<>(Comparator.comparing(Class::getName)); - } - - /** - * This seems ridiculous, but it is needed to actually convert between the two types of {@link - * Set}s. Gets around a generics error: {@code incompatible types: inference variable T has - * incompatible bounds}. - */ - private Class> casting( - Class> c) { - return c; - } } diff --git a/src/main/resources/org/jenkins/tools/test/logging/logging.properties b/src/main/resources/org/jenkins/tools/test/logging/logging.properties index fa54cd933..d638ee63a 100644 --- a/src/main/resources/org/jenkins/tools/test/logging/logging.properties +++ b/src/main/resources/org/jenkins/tools/test/logging/logging.properties @@ -29,10 +29,3 @@ handlers= java.util.logging.ConsoleHandler ############################################################ java.util.logging.ConsoleHandler.formatter = io.jenkins.lib.support_log_formatter.SupportLogFormatter - -############################################################ -# Facility-specific properties. -# Provides extra control for each logger. -############################################################ - -org.reflections.level= WARNING