From 45eeec8a724029d9f8c2175528e1b0a975de205e Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sat, 16 Nov 2019 00:40:40 +0200 Subject: [PATCH] Support any interface as an ExtensionPoint (#350) --- .../ExtensionAnnotationProcessor.java | 37 ++++++++++++++++--- .../ExtensionAnnotationProcessorTest.java | 2 +- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java b/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java index 9c629de..2faf143 100644 --- a/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java +++ b/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java @@ -52,19 +52,23 @@ import java.util.TreeSet; public class ExtensionAnnotationProcessor extends AbstractProcessor { private static final String STORAGE_CLASS_NAME = "pf4j.storageClassName"; + private static final String IGNORE_EXTENSION_POINT = "pf4j.ignoreExtensionPoint"; private Map> extensions = new HashMap<>(); // the key is the extension point private Map> oldExtensions = new HashMap<>(); // the key is the extension point private ExtensionStorage storage; + private boolean ignoreExtensionPoint; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); info("%s init", ExtensionAnnotationProcessor.class.getName()); + info("Options %s", processingEnv.getOptions()); initStorage(); + initIgnoreExtensionPoint(); } @Override @@ -81,6 +85,7 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { public Set getSupportedOptions() { Set options = new HashSet<>(); options.add(STORAGE_CLASS_NAME); + options.add(IGNORE_EXTENSION_POINT); return options; } @@ -186,11 +191,11 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { // detect extension points automatically, if they are not explicitly configured (default behaviour) else { // search in interfaces - for (TypeMirror item : extensionElement.getInterfaces()) { + List interfaces = extensionElement.getInterfaces(); + for (TypeMirror item : interfaces) { boolean isExtensionPoint = processingEnv.getTypeUtils().isSubtype(item, getExtensionPointType()); if (isExtensionPoint) { - TypeElement extensionPointElement = (TypeElement) ((DeclaredType) item).asElement(); - extensionPointElements.add(extensionPointElement); + extensionPointElements.add(getElement(item)); } } @@ -199,8 +204,18 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { if (superclass.getKind() != TypeKind.NONE) { boolean isExtensionPoint = processingEnv.getTypeUtils().isSubtype(superclass, getExtensionPointType()); if (isExtensionPoint) { - TypeElement extensionPointElement = (TypeElement) ((DeclaredType) superclass).asElement(); - extensionPointElements.add(extensionPointElement); + extensionPointElements.add(getElement(superclass)); + } + } + + // pickup the first interface + if (extensionPointElements.isEmpty() && ignoreExtensionPoint) { + if (interfaces.isEmpty()) { + error(extensionElement, "%s is not an extension (it doesn't implement any interface)", extensionElement); + } else if (interfaces.size() == 1) { + extensionPointElements.add(getElement(interfaces.get(0))); + } else { + error(extensionElement, "%s is not an extension (it implements multiple interfaces)", extensionElement); } } } @@ -242,6 +257,12 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { } } + private void initIgnoreExtensionPoint() { + // search in processing options and system properties + ignoreExtensionPoint = getProcessingEnvironment().getOptions().containsKey(IGNORE_EXTENSION_POINT) || + System.getProperty(IGNORE_EXTENSION_POINT) != null; + } + private void processExtensionElement(Element element) { // check if @Extension is put on class and not on method or constructor if (!(element instanceof TypeElement)) { @@ -250,7 +271,7 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { } // check if class extends/implements an extension point - if (!isExtension(element.asType())) { + if (!ignoreExtensionPoint && !isExtension(element.asType())) { error(element, "%s is not an extension (it doesn't implement ExtensionPoint)", element); return; } @@ -270,4 +291,8 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { } } + private TypeElement getElement(TypeMirror typeMirror) { + return (TypeElement) ((DeclaredType) typeMirror).asElement(); + } + } diff --git a/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java b/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java index 4f8dd2e..081be99 100644 --- a/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java +++ b/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java @@ -115,7 +115,7 @@ public class ExtensionAnnotationProcessorTest { public void getSupportedOptions() { ExtensionAnnotationProcessor instance = new ExtensionAnnotationProcessor(); Set result = instance.getSupportedOptions(); - assertEquals(1, result.size()); + assertEquals(2, result.size()); } @Test -- 2.39.5