]> source.dussan.org Git - pf4j.git/commitdiff
Support any interface as an ExtensionPoint (#350)
authorDecebal Suiu <decebal.suiu@gmail.com>
Fri, 15 Nov 2019 22:40:40 +0000 (00:40 +0200)
committerGitHub <noreply@github.com>
Fri, 15 Nov 2019 22:40:40 +0000 (00:40 +0200)
pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java
pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java

index 9c629dedb242e23d7e76c55292b11dafef806405..2faf1432796076323f27dbd7518de24dae5dde65 100644 (file)
@@ -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<String, Set<String>> extensions = new HashMap<>(); // the key is the extension point
     private Map<String, Set<String>> 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<String> getSupportedOptions() {
         Set<String> 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<? extends TypeMirror> 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();
+    }
+
 }
index 4f8dd2e1933399fb06c2b5beb5325ed273eb5294..081be99c9ebce784e794918a83e68757ea9e3f6b 100644 (file)
@@ -115,7 +115,7 @@ public class ExtensionAnnotationProcessorTest {
     public void getSupportedOptions() {
         ExtensionAnnotationProcessor instance = new ExtensionAnnotationProcessor();
         Set<String> result = instance.getSupportedOptions();
-        assertEquals(1, result.size());
+        assertEquals(2, result.size());
     }
 
     @Test