You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2022/10/16 06:33:41 UTC

[logging-log4j2] 02/04: Add PluginEntry.Builder to simplify code generation

This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit c5d55239bba6c9e209d079d71bd3f5c96927fb3e
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sat Oct 15 15:50:40 2022 -0500

    Add PluginEntry.Builder to simplify code generation
    
    This updates PluginProcessor to use the builder class while removing the implemented interfaces property from PluginEntry.
    
    Signed-off-by: Matt Sicker <ma...@apache.org>
---
 .../log4j/plugin/processor/PluginProcessor.java    | 65 +++++-----------------
 .../logging/log4j/plugins/di/DefaultInjector.java  | 40 ++++++-------
 .../logging/log4j/plugins/model/PluginEntry.java   | 48 ++--------------
 .../logging/log4j/plugins/model/PluginType.java    | 18 +-----
 4 files changed, 40 insertions(+), 131 deletions(-)

diff --git a/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java b/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
index c991ce8f45..87eb4197b7 100644
--- a/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
+++ b/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
@@ -34,16 +34,10 @@ import javax.lang.model.SourceVersion;
 import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ElementVisitor;
-import javax.lang.model.element.Modifier;
 import javax.lang.model.element.Name;
 import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementKindVisitor9;
 import javax.lang.model.util.Elements;
 import javax.lang.model.util.SimpleElementVisitor8;
-import javax.lang.model.util.SimpleTypeVisitor9;
-import javax.lang.model.util.Types;
 import javax.tools.Diagnostic.Kind;
 import javax.tools.FileObject;
 import javax.tools.JavaFileObject;
@@ -55,7 +49,6 @@ import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -170,33 +163,27 @@ public class PluginProcessor extends AbstractProcessor {
             writer.println("");
             writer.println("public class Log4jPlugins extends PluginService {");
             writer.println("");
-            writer.println("    private static final PluginEntry[] ENTRIES = new PluginEntry[] {");
-            StringBuilder sb = new StringBuilder();
+            writer.println("  private static final PluginEntry[] ENTRIES = new PluginEntry[] {");
             int max = list.size() - 1;
             for (int i = 0; i < list.size(); ++i) {
                 PluginEntryMirror mirror = list.get(i);
                 final PluginEntry entry = mirror.entry;
-                sb.append("        ").append("new PluginEntry(\"");
-                sb.append(entry.getKey()).append("\", \"");
-                sb.append(entry.getClassName()).append("\", \"");
-                sb.append(entry.getName()).append("\", \"");
-                final String elementName = entry.getElementType();
-                if (elementName != null) {
-                    sb.append(elementName);
+                writer.println("    PluginEntry.builder()");
+                writer.println(String.format("      .setKey(\"%s\")", entry.getKey()));
+                writer.println(String.format("      .setClassName(\"%s\")", entry.getClassName()));
+                writer.println(String.format("      .setName(\"%s\")", entry.getName()));
+                writer.println(String.format("      .setNamespace(\"%s\")", entry.getNamespace()));
+                final String elementType = entry.getElementType();
+                if (Strings.isNotEmpty(elementType)) {
+                    writer.println(String.format("      .setElementType(\"%s\")", elementType));
                 }
-                sb.append("\", ");
-                sb.append(entry.isPrintable()).append(", ");
-                sb.append(entry.isDeferChildren()).append(", \"");
-                sb.append(entry.getNamespace()).append("\"");
-                for (final Name implementedInterface : getImplementedInterfaces(mirror.element.asType())) {
-                    sb.append(", ").append(implementedInterface).append(".class");
+                if (entry.isPrintable()) {
+                    writer.println("      .setPrintable(true)");
                 }
-                sb.append(')');
-                if (i < max) {
-                    sb.append(",");
+                if (entry.isDeferChildren()) {
+                    writer.println("      .setDeferChildren(true)");
                 }
-                writer.println(sb);
-                sb.setLength(0);
+                writer.println("      .get()" + (i < max ? "," : Strings.EMPTY));
             }
             writer.println("    };");
             writer.println("    @Override");
@@ -274,30 +261,6 @@ public class PluginProcessor extends AbstractProcessor {
         }
     }
 
-    private Set<Name> getImplementedInterfaces(final TypeMirror base) {
-        final Set<Name> implementedInterfaces = new LinkedHashSet<>();
-        final Types types = processingEnv.getTypeUtils();
-        base.accept(new SimpleTypeVisitor9<Void, Void>() {
-            @Override
-            public Void visitDeclared(final DeclaredType t, final Void unused) {
-                for (final TypeMirror directSupertype : types.directSupertypes(t)) {
-                    directSupertype.accept(this, null);
-                }
-                t.asElement().accept(new ElementKindVisitor9<Void, Void>() {
-                    @Override
-                    public Void visitTypeAsInterface(final TypeElement e, final Void unused) {
-                        if (e.getModifiers().contains(Modifier.PUBLIC)) {
-                            implementedInterfaces.add(e.getQualifiedName());
-                        }
-                        return null;
-                    }
-                }, null);
-                return null;
-            }
-        }, null);
-        return implementedInterfaces;
-    }
-
     private String commonPrefix(String str1, String str2) {
         int minLength = Math.min(str1.length(), str2.length());
         for (int i = 0; i < minLength; i++) {
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
index e930f33ded..c61f10df99 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
@@ -319,10 +319,8 @@ class DefaultInjector implements Injector {
         }
         final PluginNamespace namespace = getInstance(PluginRegistry.class).getNamespace(itemKey.getNamespace(), getPluginPackages());
         final Type type = itemKey.getType();
-        final Class<T> rawType = itemKey.getRawType();
         return namespace.stream()
-                .filter(pluginType -> rawType.isInterface() && pluginType.getImplementedInterfaces().contains(rawType) ||
-                        TypeUtil.isAssignable(type, pluginType.getPluginClass()))
+                .filter(pluginType -> TypeUtil.isAssignable(type, pluginType.getPluginClass()))
                 .sorted(Comparator.comparing(PluginType::getPluginClass, OrderedComparator.INSTANCE))
                 .map(TypeUtil::cast);
     }
@@ -574,22 +572,7 @@ class DefaultInjector implements Injector {
                 .allMatch(condition -> condition.matches(key, rawType))) {
             return null;
         }
-        final Executable factory = Stream.of(rawType.getDeclaredMethods())
-                .filter(method -> Modifier.isStatic(method.getModifiers()) &&
-                        AnnotationUtil.isMetaAnnotationPresent(method, FactoryType.class))
-                .min(Comparator.comparingInt(Method::getParameterCount).thenComparing(Method::getReturnType, (c1, c2) -> {
-                    if (c1.equals(c2)) {
-                        return 0;
-                    } else if (Supplier.class.isAssignableFrom(c1)) {
-                        return -1;
-                    } else if (Supplier.class.isAssignableFrom(c2)) {
-                        return 1;
-                    } else {
-                        return c1.getName().compareTo(c2.getName());
-                    }
-                }))
-                .map(Executable.class::cast)
-                .orElseGet(() -> getInjectableConstructor(key, Set.of()));
+        final Executable factory = getInjectablePluginFactory(rawType);
         final List<InjectionPoint<?>> points = InjectionPoint.fromExecutable(factory);
         if (!factory.canAccess(null)) {
             accessor.makeAccessible(factory);
@@ -783,6 +766,25 @@ class DefaultInjector implements Injector {
         return newChain;
     }
 
+    private static Executable getInjectablePluginFactory(final Class<?> pluginClass) {
+        return Stream.of(pluginClass.getDeclaredMethods())
+                .filter(method -> Modifier.isStatic(method.getModifiers()) &&
+                        AnnotationUtil.isMetaAnnotationPresent(method, FactoryType.class))
+                .min(Comparator.comparingInt(Method::getParameterCount).thenComparing(Method::getReturnType, (c1, c2) -> {
+                    if (c1.equals(c2)) {
+                        return 0;
+                    } else if (Supplier.class.isAssignableFrom(c1)) {
+                        return -1;
+                    } else if (Supplier.class.isAssignableFrom(c2)) {
+                        return 1;
+                    } else {
+                        return c1.getName().compareTo(c2.getName());
+                    }
+                }))
+                .map(Executable.class::cast)
+                .orElseGet(() -> getInjectableConstructor(Key.forClass(pluginClass), Set.of()));
+    }
+
     private static <T> Constructor<T> getInjectableConstructor(final Key<T> key, final Set<Key<?>> chain) {
         final Class<T> rawType = key.getRawType();
         final List<Constructor<?>> injectConstructors = Stream.of(rawType.getDeclaredConstructors())
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginEntry.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginEntry.java
index f9e240e745..fb507b4dbc 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginEntry.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginEntry.java
@@ -17,6 +17,8 @@
 
 package org.apache.logging.log4j.plugins.model;
 
+import org.apache.logging.log4j.util.Strings;
+
 import java.util.function.Supplier;
 
 /**
@@ -30,32 +32,6 @@ public class PluginEntry {
     private final boolean printable;
     private final boolean deferChildren;
     private final String namespace;
-    private final Class<?>[] interfaces;
-
-    public PluginEntry(
-            String key, String className, String name, String elementType, boolean printable, boolean deferChildren, String namespace) {
-        this.key = key;
-        this.className = className;
-        this.name = name;
-        this.elementType = elementType;
-        this.printable = printable;
-        this.deferChildren = deferChildren;
-        this.namespace = namespace;
-        this.interfaces = null;
-    }
-
-    public PluginEntry(
-            final String key, final String className, final String name, final String elementType, final boolean printable,
-            final boolean deferChildren, final String namespace, final Class<?>... interfaces) {
-        this.key = key;
-        this.className = className;
-        this.name = name;
-        this.elementType = elementType;
-        this.printable = printable;
-        this.deferChildren = deferChildren;
-        this.namespace = namespace;
-        this.interfaces = interfaces;
-    }
 
     private PluginEntry(final Builder builder) {
         key = builder.getKey();
@@ -65,8 +41,6 @@ public class PluginEntry {
         printable = builder.isPrintable();
         deferChildren = builder.isDeferChildren();
         namespace = builder.getNamespace();
-        final Class<?>[] classes = builder.getInterfaces();
-        interfaces = classes != null ? classes.clone() : null;
     }
 
     public String getKey() {
@@ -97,10 +71,6 @@ public class PluginEntry {
         return namespace;
     }
 
-    public Class<?>[] getInterfaces() {
-        return interfaces;
-    }
-
     @Override
     public String toString() {
         return "PluginEntry [key=" + key + ", className=" + className + ", name=" + name + ", printable=" + printable
@@ -115,11 +85,10 @@ public class PluginEntry {
         private String key;
         private String className;
         private String name;
-        private String elementType;
+        private String elementType = Strings.EMPTY;
         private boolean printable;
         private boolean deferChildren;
-        private String namespace;
-        private Class<?>[] interfaces;
+        private String namespace = Strings.EMPTY;
 
         public String getKey() {
             return key;
@@ -184,15 +153,6 @@ public class PluginEntry {
             return this;
         }
 
-        public Class<?>[] getInterfaces() {
-            return interfaces;
-        }
-
-        public Builder setInterfaces(final Class<?>... interfaces) {
-            this.interfaces = interfaces;
-            return this;
-        }
-
         @Override
         public PluginEntry get() {
             return new PluginEntry(this);
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java
index 0c8bbcd7cd..028d56ee77 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java
@@ -19,7 +19,6 @@ package org.apache.logging.log4j.plugins.model;
 import org.apache.logging.log4j.plugins.util.TypeUtil;
 import org.apache.logging.log4j.util.LazyValue;
 
-import java.util.Set;
 import java.util.function.Supplier;
 
 /**
@@ -32,7 +31,6 @@ public class PluginType<T> {
 
     private final PluginEntry pluginEntry;
     private final Supplier<Class<T>> pluginClass;
-    private final Supplier<Set<Class<?>>> implementedInterfaces;
 
     /**
      * Constructor.
@@ -44,8 +42,6 @@ public class PluginType<T> {
             final PluginEntry pluginEntry, final Class<T> pluginClass) {
         this.pluginEntry = pluginEntry;
         this.pluginClass = () -> pluginClass;
-        final var interfaces = Set.of(pluginClass.getInterfaces());
-        this.implementedInterfaces = () -> interfaces;
     }
 
     /**
@@ -55,7 +51,7 @@ public class PluginType<T> {
      */
     public PluginType(final PluginEntry pluginEntry, final ClassLoader classLoader) {
         this.pluginEntry = pluginEntry;
-        final LazyValue<Class<T>> classProvider = LazyValue.from(() -> {
+        this.pluginClass = LazyValue.from(() -> {
             try {
                 return TypeUtil.cast(classLoader.loadClass(pluginEntry.getClassName()));
             } catch (final ClassNotFoundException e) {
@@ -63,14 +59,6 @@ public class PluginType<T> {
                         " located for element " + pluginEntry.getName(), e);
             }
         });
-        this.pluginClass = classProvider;
-        final Class<?>[] interfaces = pluginEntry.getInterfaces();
-        if (interfaces != null) {
-            final var implementedInterfaces = Set.of(interfaces);
-            this.implementedInterfaces = () -> implementedInterfaces;
-        } else {
-            this.implementedInterfaces = classProvider.map(clazz -> Set.of(clazz.getInterfaces()));
-        }
     }
 
     public PluginEntry getPluginEntry() {
@@ -81,10 +69,6 @@ public class PluginType<T> {
         return pluginClass.get();
     }
 
-    public Set<Class<?>> getImplementedInterfaces() {
-        return implementedInterfaces.get();
-    }
-
     public String getElementType() {
         return pluginEntry.getElementType();
     }