ppkarwasz commented on code in PR #3505:
URL: https://github.com/apache/logging-log4j2/pull/3505#discussion_r1976724741


##########
log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingFileAppenderUpdateDataTest.java:
##########
@@ -82,15 +81,15 @@ void after() {
     @Test
     void testClosingLoggerContext() {
         // initial config with indexed rollover
-        try (final LoggerContext loggerContext1 =
+        try (final LoggerContext tLoggerContext1 =

Review Comment:
   This isn't really necessary (and the 3 changes below).



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ComponentBuilder.java:
##########
@@ -19,78 +19,199 @@
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.util.Builder;
+import org.jspecify.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
 
 /**
  * Builds arbitrary components and is the base type for the provided 
components.
  * @param <T> The ComponentBuilder's own type for fluent APIs.
  * @since 2.4
  */
+@ProviderType
 public interface ComponentBuilder<T extends ComponentBuilder<T>> extends 
Builder<Component> {
 
     /**
-     * Adds a String attribute.
+     * Returns the name of the component.
+     * @return The component's name or {@code null} if it doesn't have one.
+     */
+    @Nullable
+    String getName();
+
+    /**
+     * Retrieves the {@code ConfigurationBuilder}.
+     * @return The ConfigurationBuilder.
+     */
+    ConfigurationBuilder<? extends Configuration> getBuilder();
+
+    /**
+     * Adds a sub component.
+     * @param builder The Assembler for the subcomponent with all of its 
attributes and sub-components set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
+     */
+    T addComponent(ComponentBuilder<?> builder);
+
+    /**
+     * Sets a String attribute.
+     * <p>
+     *   If the given {@code level} value is {@code null}, the component 
attribute with the given key
+     *   will be removed (if present).
+     * </p>
      * @param key The attribute key.
      * @param value The value of the attribute.
-     * @return This ComponentBuilder.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code key} is {@code null}
      */
-    T addAttribute(String key, String value);
+    T setAttribute(String key, @Nullable String value);
 
     /**
-     * Adds a logging Level attribute.
+     * Sets a logging Level attribute.
+     * <p>
+     *   If the given {@code level} value is {@code null}, the component 
attribute with the given key
+     *   will be removed (if present).
+     * </p>
      * @param key The attribute key.
      * @param level The logging Level.
-     * @return This ComponentBuilder.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code key} is {@code null}
      */
-    T addAttribute(String key, Level level);
+    T setAttribute(String key, @Nullable Level level);

Review Comment:
   We can probably provide a `default` implementation for these methods.



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java:
##########
@@ -16,430 +16,587 @@
  */
 package org.apache.logging.log4j.core.config.builder.api;
 
+import aQute.bnd.annotation.baseline.BaselineIgnore;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.concurrent.TimeUnit;
 import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Filter.Result;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.Logger;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.async.AsyncLogger;
+import org.apache.logging.log4j.core.config.AppenderRef;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.CustomLevels;
+import org.apache.logging.log4j.core.config.LoggerConfig.RootLogger;
+import org.apache.logging.log4j.core.config.Property;
+import org.apache.logging.log4j.core.script.Script;
+import org.apache.logging.log4j.core.script.ScriptFile;
 import org.apache.logging.log4j.core.util.Builder;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.jspecify.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
 
 /**
  * Interface for building logging configurations.
  * @param <T> The Configuration type created by this builder.
  * @since 2.4
  */
+@ProviderType
 public interface ConfigurationBuilder<T extends Configuration> extends 
Builder<T> {
 
     /**
-     * Adds a ScriptComponent.
-     * @param builder The ScriptComponentBuilder with all of its attributes 
and sub components set.
-     * @return this builder instance.
+     * Adds the {@link Script} component built by the given {@code 
ScriptComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code ScriptComponentBuilder} to add with all of 
its attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(ScriptComponentBuilder builder);
 
     /**
-     * Adds a ScriptFileComponent.
-     * @param builder The ScriptFileComponentBuilder with all of its 
attributes and sub components set.
-     * @return this builder instance.
+     * Adds the {@link ScriptFile} component built by the given {@code 
ScriptFileComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code ScriptFileComponentBuilder} to add with all 
of its attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(ScriptFileComponentBuilder builder);
 
     /**
-     * Adds an AppenderComponent.
-     * @param builder The AppenderComponentBuilder with all of its attributes 
and sub components set.
-     * @return this builder instance.
+     * Adds the {@link Appender} component built by the given {@code 
AppenderComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code AppenderComponentBuilder} to add with all of 
its attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(AppenderComponentBuilder builder);
 
     /**
-     * Adds a CustomLevel component.
-     * @param builder The CustomLevelComponentBuilder with all of its 
attributes set.
-     * @return this builder instance.
+     * Adds the {@link CustomLevels} component built by the given {@code 
CustomLevelComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code CustomLevelComponentBuilder} with all of its 
attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(CustomLevelComponentBuilder builder);
 
     /**
-     * Adds a Filter component.
-     * @param builder the FilterComponentBuilder with all of its attributes 
and sub components set.
-     * @return this builder instance.
+     * Adds the {@link Filter} component built by the given {@code 
FilterComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code FilterComponentBuilder} with all of its 
attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(FilterComponentBuilder builder);
 
     /**
-     * Adds a Logger component.
-     * @param builder The LoggerComponentBuilder with all of its attributes 
and sub components set.
-     * @return this builder instance.
+     * Adds the {@link Logger} component built by the given {@code 
LoggerComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code LoggerComponentBuilder} with all of its 
attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(LoggerComponentBuilder builder);
 
     /**
-     * Adds the root Logger component.
-     * @param builder The RootLoggerComponentBuilder with all of its 
attributes and sub components set.
-     * @return this builder instance.
+     * Adds the {@link RootLogger} component built by the given {@code 
RootLoggerComponentBuilder}
+     * to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code RootLoggerComponentBuilder} with all of its 
attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(RootLoggerComponentBuilder builder);
 
     /**
-     * Adds a Property key and value.
-     * @param key The property key.
-     * @param value The property value.
-     * @return this builder instance.
+     * Adds a the {@link Property} component built by the given {@link 
PropertyComponentBuilder}.
+     * @param builder the {@code PropertyComponentBuilder} to add
+     * @return this builder (for chaining)
      */
-    ConfigurationBuilder<T> addProperty(String key, String value);
+    ConfigurationBuilder<T> add(PropertyComponentBuilder builder);
 
     /**
-     * Returns a builder for creating Async Loggers.
-     * @param name The name of the Logger.
-     * @param language The script language
-     * @param text The script to execute.
-     * @return A new ScriptComponentBuilder.
+     * Adds a {@link Property} component with the given {@code key} and {@code 
value}.
+     *
+     * @param name the property name
+     * @param value the property value
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
+     * @deprecated use {@link #add(PropertyComponentBuilder)}
      */
-    ScriptComponentBuilder newScript(String name, String language, String 
text);
+    @Deprecated
+    ConfigurationBuilder<T> addProperty(@Nullable String name, @Nullable 
String value);

Review Comment:
   The `@throws` description is a copy/paste problem.
   
   Neither `name` nor `value` should be `null` IMHO.



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/CompositeFilterComponentBuilder.java:
##########
@@ -16,9 +16,71 @@
  */
 package org.apache.logging.log4j.core.config.builder.api;
 
+import org.apache.logging.log4j.core.Filter.Result;
+import org.apache.logging.log4j.core.filter.CompositeFilter;
+import org.jspecify.annotations.Nullable;
+
 /**
- * Wraps multiple Filter Component builders.
+ * A builder interface for constructing and configuring {@link 
CompositeFilter} components in a Log4j configuration.
+ *
+ * <p>
+ *   Instances of this builder are designed for single-threaded use and are 
not thread-safe. Developers
+ *   should avoid sharing instances between threads.
+ * </p>
  *
  * @since 2.4
  */
-public interface CompositeFilterComponentBuilder extends 
FilterableComponentBuilder<CompositeFilterComponentBuilder> {}
+public interface CompositeFilterComponentBuilder extends 
FilterableComponentBuilder<CompositeFilterComponentBuilder> {
+
+    /**
+     * Adds the 'onMatch' attribute to the filter component.
+     * <p>
+     *   If the given {@code onMatch} argument is {@code} the attribute will 
be removed (if present).
+     * </p>
+     *
+     * @param onMatch the attribute value
+     * @return this builder (for chaining)
+     */
+    default CompositeFilterComponentBuilder setOnMatchAttribute(@Nullable 
String onMatch) {
+        return setAttribute("onMatch", onMatch);
+    }

Review Comment:
   `CompositeFilter` does not have neither an `onMatch` nor an `onMismatch` 
attribute.



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultComponentBuilder.java:
##########
@@ -17,104 +17,217 @@
 package org.apache.logging.log4j.core.config.builder.impl;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.builder.api.Component;
 import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
+import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
 
 /**
- * Generic component that captures attributes and Components in preparation 
for assembling the Appender's
- * Component.
+ * Generic base default {@link ComponentBuilder} implementation that captures 
attributes and children
+ * which are used to build a new {@link Component} instance.
  *
+ * @param <T> the type of the component builder
+ * @param <CB> the type of the configuration builder
  * @since 2.4
  */
+@ProviderType
 class DefaultComponentBuilder<T extends ComponentBuilder<T>, CB extends 
ConfigurationBuilder<? extends Configuration>>
         implements ComponentBuilder<T> {
 
     private final CB builder;
-    private final String type;
+    private final String pluginType;
     private final Map<String, String> attributes = new LinkedHashMap<>();
     private final List<Component> components = new ArrayList<>();
-    private final String name;
-    private final String value;
-
-    public DefaultComponentBuilder(final CB builder, final String type) {
-        this(builder, null, type, null);
+    private final @Nullable String name;
+    private final @Nullable String value;
+
+    /**
+     * Constructs a new instance with the given configuration builder and 
plugin-type with {@code null} name and value.
+     * @param builder the configuration builder
+     * @param pluginType the plugin-type of the component being built
+     * @throws NullPointerException if either {@code builder} or {@code type} 
argument is null
+     */
+    public DefaultComponentBuilder(final CB builder, final String pluginType) {
+        this(builder, pluginType, null, null);
     }
 
-    public DefaultComponentBuilder(final CB builder, final String name, final 
String type) {
-        this(builder, name, type, null);
+    /**
+     * Constructs a new instancer with the given configuration builder, 
plugin-type, name, and {@code null} value.
+     * @param builder the configuration builder
+     * @param pluginType the plugin-type of the component being built
+     * @param name the component name
+     * @throws NullPointerException if either {@code builder} or {@code type} 
argument is null
+     */
+    public DefaultComponentBuilder(final CB builder, final String pluginType, 
final @Nullable String name) {
+        this(builder, pluginType, name, null);
     }
 
-    public DefaultComponentBuilder(final CB builder, final String name, final 
String type, final String value) {
-        this.type = type;
-        this.builder = builder;
+    /**
+     * Constructs a new instance with the given configuration builder, 
plugin-type, name and value.
+     * @param builder the configuration builder
+     * @param pluginType the type (plugin-type) of the component being built
+     * @param name the component name
+     * @param value the component value
+     * @throws NullPointerException if either {@code builder} or {@code type} 
argument is null
+     */
+    public DefaultComponentBuilder(
+            final CB builder, final String pluginType, final @Nullable String 
name, final @Nullable String value) {
+        super();
+        this.builder = Objects.requireNonNull(builder, "The 'builder' argument 
must not be null.");
+        this.pluginType = Objects.requireNonNull(pluginType, "The 'type' 
argument must not be null.");
         this.name = name;
         this.value = value;
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final boolean value) {
-        return put(key, Boolean.toString(value));
+    public Component build() {
+        final Component component = new Component(pluginType, name, value);
+        component.getAttributes().putAll(attributes);
+        component.getComponents().addAll(components);
+        return component;
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final Enum<?> value) {
-        return put(key, value.name());
+    public T addComponent(final ComponentBuilder<?> builder) {
+        Objects.requireNonNull(builder, "The 'builder' argument must not be 
null.");
+        components.add(builder.build());
+        return self();
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final int value) {
-        return put(key, Integer.toString(value));
+    public @NonNull CB getBuilder() {

Review Comment:
   ```suggestion
       public CB getBuilder() {
   ```
   
   Isn't `@NonNull` the default?



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java:
##########
@@ -334,7 +332,7 @@ private static <B extends ComponentBuilder<B>> 
ComponentBuilder<B> createCompone
             final ComponentBuilder<?> parent, final String key, final 
Properties properties) {
         final String name = (String) properties.remove(CONFIG_NAME);
         final String type = (String) properties.remove(CONFIG_TYPE);
-        if (Strings.isEmpty(type)) {
+        if (type == null || Strings.isEmpty(type)) {

Review Comment:
   ```suggestion
           if (Strings.isEmpty(type)) {
   ```
   
   `Strings.isEmpty` is `null`-safe.



##########
src/changelog/.2.x.x/2791_rework_ComponentBuilder_API.xml:
##########
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xmlns="https://logging.apache.org/xml/ns";
+       xsi:schemaLocation="https://logging.apache.org/xml/ns 
https://logging.apache.org/xml/ns/log4j-changelog-0.xsd";
+       type="changed">
+  <issue id="2791" 
link="https://github.com/apache/logging-log4j2/issues/2791"/>
+  <description format="asciidoc">
+    Fix problem when null attribute values are set on DefaultComponentBuilder. 
GitHub issue #2791.
+    Added JVerify annotations to config.builder.* packages.

Review Comment:
   ```suggestion
       Added JSpecify annotations to config.builder.* packages.
   ```



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/Component.java:
##########
@@ -74,7 +94,27 @@ public String getPluginType() {
         return pluginType;
     }
 
-    public String getValue() {
+    public @Nullable String getValue() {
         return value;
     }
+
+    /**
+     * Puts the given key/value pair to the attribute map.
+     * <p>
+     *   If the new value is {@code null}, than any existing entry with the 
given {@code key} is ejected from the map.
+     * </p>
+     * @param key the key
+     * @param newValue the new value
+     * @return the previous value or {@code null} if none was set
+     */
+    protected @Nullable String putAttribute(final String key, final @Nullable 
String newValue) {

Review Comment:
   Why is this `protected`?
   
   It has a better sounding name than `addAttribute`. Maybe `addAttribute` 
should be deprecated (possibly with an Error Prone 
[`@InlineMe`](https://errorprone.info/docs/inlineme) annotation) and this 
should be `public`?



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/AppenderRefComponentBuilder.java:
##########
@@ -16,8 +16,58 @@
  */
 package org.apache.logging.log4j.core.config.builder.api;
 
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.config.AppenderRef;
+import org.jspecify.annotations.Nullable;
+
 /**
- * Assembler for constructing AppenderRef Components.
+ * A builder interface for constructing and configuring {@link AppenderRef} 
components in a Log4j configuration.
+ *
+ * <p>
+ *   Instances of this builder are designed for single-threaded use and are 
not thread-safe. Developers
+ *   should avoid sharing instances between threads.
+ * </p>
+ *
  * @since 2.4
  */
-public interface AppenderRefComponentBuilder extends 
FilterableComponentBuilder<AppenderRefComponentBuilder> {}
+public interface AppenderRefComponentBuilder extends 
FilterableComponentBuilder<AppenderRefComponentBuilder> {
+
+    /**
+     * Sets the "{@code level}" attribute on the appender-reference component.
+     * <p>
+     *   If the given {@code level} is {@code null}, the attribute will be 
removed from the component.
+     * </p>
+     *
+     * @param level the level
+     * @return this builder (for chaining)
+     */
+    default AppenderRefComponentBuilder setLevelAttribute(@Nullable String 
level) {

Review Comment:
   IMHO `setLevel` would be a better naming choice: it is not ambiguous and it 
is shorter.
   
   Should we remove the `Attribute` suffix from all new methods?



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/Component.java:
##########
@@ -20,45 +20,65 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import org.jspecify.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
 
 /**
  * Container for building Configurations. This class is not normally directly 
manipulated by users
  * of the Assembler API.
  * @since 2.4
  */
+@ProviderType

Review Comment:
   ```suggestion
   ```
   
   This class is not meant to be extended by neither consumers nor providers, 
so no annotation is needed.



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/LoggableComponentBuilder.java:
##########
@@ -16,17 +16,97 @@
  */
 package org.apache.logging.log4j.core.config.builder.api;
 
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.config.LoggerConfig.RootLogger;
+import org.jspecify.annotations.Nullable;
+
 /**
- * Common component builder for Logger and RootLogger elements.
+ * A common builder interface for constructing and configuring {@link Logger} 
and {@link RootLogger}
+ * components in a Log4j configuration.
+ *
+ * <p>
+ *   Instances of this builder are designed for single-threaded use and are 
not thread-safe. Developers
+ *   should avoid sharing instances between threads.
+ * </p>
  *
  * @since 2.6
  */
 public interface LoggableComponentBuilder<T extends ComponentBuilder<T>> 
extends FilterableComponentBuilder<T> {
+
+    /**
+     * Add an {@link AppenderRefComponentBuilder} to this logger component 
builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code AppenderRefComponentBuilder} with all of its 
attributes and subcomponents set.
+     * @return this component builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} argument is 
{@code null}
+     */
+    T add(AppenderRefComponentBuilder builder);
+
+    /**
+     * Sets the "{@code additivity}" attribute on the logger component.
+     *
+     * @param additivity {@code true} if additive; otherwise, {@code false}
+     * @return this builder (for chaining)
+     */
+    default T setAdditivityAttribute(boolean additivity) {

Review Comment:
   This is not useful for all logger builders. For example `Root` and 
`AsyncRoot` do not have an `additivity` attribute, since they don't have a 
parent logger.



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/BuiltConfiguration.java:
##########
@@ -20,38 +20,64 @@
 import java.io.InputStream;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.config.AbstractConfiguration;
+import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.ConfigurationSource;
 import org.apache.logging.log4j.core.config.Node;
 import org.apache.logging.log4j.core.config.Reconfigurable;
 import org.apache.logging.log4j.core.config.builder.api.Component;
-import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
+import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
 import org.apache.logging.log4j.core.config.status.StatusConfiguration;
 import org.apache.logging.log4j.core.util.Patterns;
+import org.jspecify.annotations.Nullable;
 
 /**
- * This is the general version of the Configuration created by the Builder. It 
may be extended to
- * enhance its functionality.
+ * A {@link Configuration} implementation that is built using a {@link 
ConfigurationBuilder} implementaion.
+ * <p>
+ *   This class may be extended to enhance its functionality.
+ * </p>
  *
  * @since 2.4
  */
 public class BuiltConfiguration extends AbstractConfiguration {
+
+    private static final String DEFAULT_CONTENT_TYPE = "text";
+
     private final StatusConfiguration statusConfig;
-    protected Component rootComponent;
-    private Component loggersComponent;
-    private Component appendersComponent;
-    private Component filtersComponent;
-    private Component propertiesComponent;
-    private Component customLevelsComponent;
-    private Component scriptsComponent;
-    private String contentType = "text";
+    private String contentType = DEFAULT_CONTENT_TYPE;
+
+    protected @Nullable Component rootComponent;

Review Comment:
   ```suggestion
       protected Component rootComponent;
   ```
   
   It is assigned to a non-null value in the constructor.



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/BuiltConfiguration.java:
##########
@@ -78,45 +104,63 @@ public BuiltConfiguration(
                     customLevelsComponent = component;
                     break;
                 }
+                default: {
+                    // NO-OP
+                    break;
+                }
             }
         }
+
         this.rootComponent = rootComponent;
     }
 
+    /** {@inheritDoc} */
     @Override
     public void setup() {
+
         final List<Node> children = rootNode.getChildren();
-        if (propertiesComponent.getComponents().size() > 0) {
+
+        if (propertiesComponent != null && 
!propertiesComponent.getComponents().isEmpty()) {
             children.add(convertToNode(rootNode, propertiesComponent));
         }
-        if (scriptsComponent.getComponents().size() > 0) {
+
+        if (scriptsComponent != null && 
!scriptsComponent.getComponents().isEmpty()) {

Review Comment:
   While this only modifies pre-existing code, I don't think this logic is at 
all necessary:
   
   - we extract from `rootComponent` **some**, but not all the children.
   - then we convert those `Component` objects into `Node`.
   - we add those nodes to `rootNode`.
   
   I think we can simplify this logic to a single loop on **all** the children 
of `rootComponent`. Maybe we could treat filters differently, but not 
necessarily.



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultAppenderRefComponentBuilder.java:
##########
@@ -16,24 +16,40 @@
  */
 package org.apache.logging.log4j.core.config.builder.impl;
 
+import org.apache.logging.log4j.core.config.AppenderRef;
 import org.apache.logging.log4j.core.config.Configuration;
 import 
org.apache.logging.log4j.core.config.builder.api.AppenderRefComponentBuilder;
 import org.apache.logging.log4j.core.config.builder.api.FilterComponentBuilder;
+import org.osgi.annotation.versioning.ProviderType;
 
 /**
- * Holds the Appender Component attributes and subcomponents.
+ * A default implementation of the {@link AppenderRefComponentBuilder} 
interface for building
+ * an {@link AppenderRef} component for a Log4j configuration.
+ *
+ * <p>
+ *   Note: This builder is not thread-safe. Instances should not be shared 
between threads.
+ * </p>
  *
  * @since 2.4
  */
+@ProviderType

Review Comment:
   `@ProviderType` makes sense on API classes, but not much on implementations: 
no one is expected to extend the implementations and they don't contain 
abstract methods (which is the only component treated differently by 
`@ConsumerType` and `@ProviderType`.



##########
log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/Configurator1Test.java:
##########
@@ -430,42 +429,42 @@ void testBuilder() {
 
     @Test
     void testRolling() {
-        final ConfigurationBuilder<BuiltConfiguration> builder = 
ConfigurationBuilderFactory.newConfigurationBuilder();
+        final ConfigurationBuilder<?> builder = 
ConfigurationBuilderFactory.newConfigurationBuilder();
 
         builder.setStatusLevel(Level.ERROR);
         builder.setConfigurationName("RollingBuilder");
         // create the console appender
         AppenderComponentBuilder appenderBuilder =
-                builder.newAppender("Stdout", 
"CONSOLE").addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
+                builder.newAppender("Stdout", 
"CONSOLE").setAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
         appenderBuilder.add(
-                builder.newLayout("PatternLayout").addAttribute("pattern", "%d 
[%t] %-5level: %msg%n%throwable"));
+                builder.newLayout("PatternLayout").setAttribute("pattern", "%d 
[%t] %-5level: %msg%n%throwable"));
         builder.add(appenderBuilder);
 
         final LayoutComponentBuilder layoutBuilder =
-                builder.newLayout("PatternLayout").addAttribute("pattern", "%d 
[%t] %-5level: %msg%n");
-        final ComponentBuilder triggeringPolicy = 
builder.newComponent("Policies")
-                
.addComponent(builder.newComponent("CronTriggeringPolicy").addAttribute("schedule",
 "0 0 0 * * ?"))
-                
.addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size",
 "100M"));
+                builder.newLayout("PatternLayout").setAttribute("pattern", "%d 
[%t] %-5level: %msg%n");
+        final ComponentBuilder<?> triggeringPolicy = 
builder.newComponent("Policies")
+                
.addComponent(builder.newComponent("CronTriggeringPolicy").setAttribute("schedule",
 "0 0 0 * * ?"))
+                
.addComponent(builder.newComponent("SizeBasedTriggeringPolicy").setAttribute("size",
 "100M"));
         appenderBuilder = builder.newAppender("rolling", "RollingFile")
-                .addAttribute("fileName", "target/rolling.log")
-                .addAttribute("filePattern", 
"target/archive/rolling-%d{MM-dd-yy}.log.gz")
+                .setAttribute("fileName", "target/rolling.log")
+                .setAttribute("filePattern", 
"target/archive/rolling-%d{MM-dd-yy}.log.gz")
                 .add(layoutBuilder)
                 .addComponent(triggeringPolicy);
         builder.add(appenderBuilder);
 
         // create the new logger
         builder.add(builder.newLogger("TestLogger", Level.DEBUG)
                 .add(builder.newAppenderRef("rolling"))
-                .addAttribute("additivity", false));
+                .setAdditivityAttribute(false));
 
         
builder.add(builder.newRootLogger(Level.DEBUG).add(builder.newAppenderRef("rolling")));
         final Configuration config = builder.build();
         config.initialize();
         assertNotNull(config.getAppender("rolling"), "No rolling file 
appender");
         assertEquals("RollingBuilder", config.getName(), "Unexpected 
Configuration");
         // Initialize the new configuration
-        final LoggerContext ctx = Configurator.initialize(config);
-        Configurator.shutdown(ctx);
+        final LoggerContext tCtx = Configurator.initialize(config);
+        Configurator.shutdown(tCtx);

Review Comment:
   I don't really see the purpose of this refactoring.



##########
log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessagePatternConverterTest.java:
##########
@@ -80,8 +81,9 @@ void testPatternAndParameterizedMessageDateLookup() {
 
     @Test
     void testDefaultDisabledLookup() {
-        final Configuration config =
-                new DefaultConfigurationBuilder().addProperty("foo", 
"bar").build(true);
+        final ConfigurationBuilder<?> configurationBuilder = 
ConfigurationBuilderFactory.newConfigurationBuilder();
+        configurationBuilder.add(configurationBuilder.newProperty("foo", 
"bar"));
+        final Configuration config = configurationBuilder.build(true);

Review Comment:
   Should we profit from the fluent API here?



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultComponentBuilder.java:
##########
@@ -17,104 +17,217 @@
 package org.apache.logging.log4j.core.config.builder.impl;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.builder.api.Component;
 import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
+import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
 
 /**
- * Generic component that captures attributes and Components in preparation 
for assembling the Appender's
- * Component.
+ * Generic base default {@link ComponentBuilder} implementation that captures 
attributes and children
+ * which are used to build a new {@link Component} instance.
  *
+ * @param <T> the type of the component builder
+ * @param <CB> the type of the configuration builder
  * @since 2.4
  */
+@ProviderType
 class DefaultComponentBuilder<T extends ComponentBuilder<T>, CB extends 
ConfigurationBuilder<? extends Configuration>>
         implements ComponentBuilder<T> {
 
     private final CB builder;
-    private final String type;
+    private final String pluginType;
     private final Map<String, String> attributes = new LinkedHashMap<>();
     private final List<Component> components = new ArrayList<>();
-    private final String name;
-    private final String value;
-
-    public DefaultComponentBuilder(final CB builder, final String type) {
-        this(builder, null, type, null);
+    private final @Nullable String name;
+    private final @Nullable String value;
+
+    /**
+     * Constructs a new instance with the given configuration builder and 
plugin-type with {@code null} name and value.
+     * @param builder the configuration builder
+     * @param pluginType the plugin-type of the component being built
+     * @throws NullPointerException if either {@code builder} or {@code type} 
argument is null
+     */
+    public DefaultComponentBuilder(final CB builder, final String pluginType) {
+        this(builder, pluginType, null, null);
     }
 
-    public DefaultComponentBuilder(final CB builder, final String name, final 
String type) {
-        this(builder, name, type, null);
+    /**
+     * Constructs a new instancer with the given configuration builder, 
plugin-type, name, and {@code null} value.
+     * @param builder the configuration builder
+     * @param pluginType the plugin-type of the component being built
+     * @param name the component name
+     * @throws NullPointerException if either {@code builder} or {@code type} 
argument is null
+     */
+    public DefaultComponentBuilder(final CB builder, final String pluginType, 
final @Nullable String name) {
+        this(builder, pluginType, name, null);
     }
 
-    public DefaultComponentBuilder(final CB builder, final String name, final 
String type, final String value) {
-        this.type = type;
-        this.builder = builder;
+    /**
+     * Constructs a new instance with the given configuration builder, 
plugin-type, name and value.
+     * @param builder the configuration builder
+     * @param pluginType the type (plugin-type) of the component being built
+     * @param name the component name
+     * @param value the component value
+     * @throws NullPointerException if either {@code builder} or {@code type} 
argument is null
+     */
+    public DefaultComponentBuilder(
+            final CB builder, final String pluginType, final @Nullable String 
name, final @Nullable String value) {
+        super();
+        this.builder = Objects.requireNonNull(builder, "The 'builder' argument 
must not be null.");
+        this.pluginType = Objects.requireNonNull(pluginType, "The 'type' 
argument must not be null.");
         this.name = name;
         this.value = value;
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final boolean value) {
-        return put(key, Boolean.toString(value));
+    public Component build() {
+        final Component component = new Component(pluginType, name, value);
+        component.getAttributes().putAll(attributes);
+        component.getComponents().addAll(components);
+        return component;
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final Enum<?> value) {
-        return put(key, value.name());
+    public T addComponent(final ComponentBuilder<?> builder) {
+        Objects.requireNonNull(builder, "The 'builder' argument must not be 
null.");
+        components.add(builder.build());
+        return self();
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final int value) {
-        return put(key, Integer.toString(value));
+    public @NonNull CB getBuilder() {
+        return builder;
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final Level level) {
-        return put(key, level.toString());
+    public @Nullable String getName() {
+        return name;
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final Object value) {
-        return put(key, value.toString());
+    public T setAttribute(final String key, final boolean value) {
+        return putAttribute(key, Boolean.toString(value));
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final String value) {
-        return put(key, value);
+    public T setAttribute(final String key, final int value) {
+        return putAttribute(key, Integer.toString(value));
     }
 
+    /** {@inheritDoc} */
     @Override
-    @SuppressWarnings("unchecked")
-    public T addComponent(final ComponentBuilder<?> builder) {
-        components.add(builder.build());
-        return (T) this;
+    public T setAttribute(final String key, final @Nullable Enum<?> value) {
+        return putAttribute(key, (value != null) ? value.name() : null);
     }
 
+    /** {@inheritDoc} */
     @Override
-    public Component build() {
-        final Component component = new Component(type, name, value);
-        component.getAttributes().putAll(attributes);
-        component.getComponents().addAll(components);
-        return component;
+    public T setAttribute(final String key, final @Nullable Level level) {
+        return putAttribute(key, (level != null) ? level.toString() : null);
     }
 
+    /** {@inheritDoc} */
     @Override
-    public CB getBuilder() {
-        return builder;
+    public T setAttribute(final String key, final @Nullable Object value) {
+        return putAttribute(key, Objects.toString(value, null));
     }
 
+    /** {@inheritDoc} */
     @Override
-    public String getName() {
-        return name;
+    public T setAttribute(final String key, final @Nullable String value) {
+        return putAttribute(key, value);
+    }
+
+    /**
+     * Clears the internal state removing all configured attributes and 
components.
+     * <p>
+     *   This method is primarily intended to be used in testing.
+     * </p>
+     */
+    protected void clear() {
+        synchronized (this) {
+            attributes.clear();
+            components.clear();
+        }

Review Comment:
   Since the class is not thread-safe anyway, do we need this?



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java:
##########
@@ -16,430 +16,587 @@
  */
 package org.apache.logging.log4j.core.config.builder.api;
 
+import aQute.bnd.annotation.baseline.BaselineIgnore;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.concurrent.TimeUnit;
 import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Filter.Result;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.Logger;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.async.AsyncLogger;
+import org.apache.logging.log4j.core.config.AppenderRef;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.CustomLevels;
+import org.apache.logging.log4j.core.config.LoggerConfig.RootLogger;
+import org.apache.logging.log4j.core.config.Property;
+import org.apache.logging.log4j.core.script.Script;
+import org.apache.logging.log4j.core.script.ScriptFile;
 import org.apache.logging.log4j.core.util.Builder;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.jspecify.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
 
 /**
  * Interface for building logging configurations.
  * @param <T> The Configuration type created by this builder.
  * @since 2.4
  */
+@ProviderType
 public interface ConfigurationBuilder<T extends Configuration> extends 
Builder<T> {
 
     /**
-     * Adds a ScriptComponent.
-     * @param builder The ScriptComponentBuilder with all of its attributes 
and sub components set.
-     * @return this builder instance.
+     * Adds the {@link Script} component built by the given {@code 
ScriptComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code ScriptComponentBuilder} to add with all of 
its attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(ScriptComponentBuilder builder);
 
     /**
-     * Adds a ScriptFileComponent.
-     * @param builder The ScriptFileComponentBuilder with all of its 
attributes and sub components set.
-     * @return this builder instance.
+     * Adds the {@link ScriptFile} component built by the given {@code 
ScriptFileComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code ScriptFileComponentBuilder} to add with all 
of its attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(ScriptFileComponentBuilder builder);
 
     /**
-     * Adds an AppenderComponent.
-     * @param builder The AppenderComponentBuilder with all of its attributes 
and sub components set.
-     * @return this builder instance.
+     * Adds the {@link Appender} component built by the given {@code 
AppenderComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code AppenderComponentBuilder} to add with all of 
its attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(AppenderComponentBuilder builder);
 
     /**
-     * Adds a CustomLevel component.
-     * @param builder The CustomLevelComponentBuilder with all of its 
attributes set.
-     * @return this builder instance.
+     * Adds the {@link CustomLevels} component built by the given {@code 
CustomLevelComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code CustomLevelComponentBuilder} with all of its 
attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(CustomLevelComponentBuilder builder);
 
     /**
-     * Adds a Filter component.
-     * @param builder the FilterComponentBuilder with all of its attributes 
and sub components set.
-     * @return this builder instance.
+     * Adds the {@link Filter} component built by the given {@code 
FilterComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code FilterComponentBuilder} with all of its 
attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(FilterComponentBuilder builder);
 
     /**
-     * Adds a Logger component.
-     * @param builder The LoggerComponentBuilder with all of its attributes 
and sub components set.
-     * @return this builder instance.
+     * Adds the {@link Logger} component built by the given {@code 
LoggerComponentBuilder} to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code LoggerComponentBuilder} with all of its 
attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(LoggerComponentBuilder builder);
 
     /**
-     * Adds the root Logger component.
-     * @param builder The RootLoggerComponentBuilder with all of its 
attributes and sub components set.
-     * @return this builder instance.
+     * Adds the {@link RootLogger} component built by the given {@code 
RootLoggerComponentBuilder}
+     * to this builder.
+     * <p>
+     *   Note: the provided {@code builder} will be built by this method; 
therefore, it must be fully configured
+     *   <i>before</i> calling this method.  Changes to the builder after 
calling this method will not have
+     *   any effect.
+     * </p>
+     *
+     * @param builder The {@code RootLoggerComponentBuilder} with all of its 
attributes and subcomponents set.
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
      */
     ConfigurationBuilder<T> add(RootLoggerComponentBuilder builder);
 
     /**
-     * Adds a Property key and value.
-     * @param key The property key.
-     * @param value The property value.
-     * @return this builder instance.
+     * Adds a the {@link Property} component built by the given {@link 
PropertyComponentBuilder}.
+     * @param builder the {@code PropertyComponentBuilder} to add
+     * @return this builder (for chaining)
      */
-    ConfigurationBuilder<T> addProperty(String key, String value);
+    ConfigurationBuilder<T> add(PropertyComponentBuilder builder);
 
     /**
-     * Returns a builder for creating Async Loggers.
-     * @param name The name of the Logger.
-     * @param language The script language
-     * @param text The script to execute.
-     * @return A new ScriptComponentBuilder.
+     * Adds a {@link Property} component with the given {@code key} and {@code 
value}.
+     *
+     * @param name the property name
+     * @param value the property value
+     * @return this builder (for chaining)
+     * @throws NullPointerException if the given {@code builder} is {@code 
null}
+     * @deprecated use {@link #add(PropertyComponentBuilder)}
      */
-    ScriptComponentBuilder newScript(String name, String language, String 
text);
+    @Deprecated
+    ConfigurationBuilder<T> addProperty(@Nullable String name, @Nullable 
String value);
 
     /**
-     * Returns a builder for creating Async Loggers.
-     * @param path The location of the script file.
-     * @return A new ScriptFileComponentBuilder.
+     * Returns a {@link ScriptComponentBuilder} for creating a {@link Script} 
component.
+     * @param name the script name
+     * @param language the script language
+     * @param text the script to execute
+     * @return the new component builder instance
      */
-    ScriptFileComponentBuilder newScriptFile(String path);
+    ScriptComponentBuilder newScript(@Nullable String name, @Nullable String 
language, @Nullable String text);
 
     /**
-     * Returns a builder for creating Async Loggers.
-     * @param name The name of the script file.
-     * @param path The location of the script file.
-     * @return A new ScriptFileComponentBuilder.
+     * Returns a {@link ScriptFileComponentBuilder} for creating a {@link 
ScriptFile} component.
+     * @param path the script file path
+     * @return the new component builder instance
      */
-    ScriptFileComponentBuilder newScriptFile(String name, String path);
+    ScriptFileComponentBuilder newScriptFile(@Nullable String path);
 
     /**
-     * Returns a builder for creating Appenders.
-     * @param name The name of the Appender.
-     * @param pluginName The Plugin type of the Appender.
-     * @return A new AppenderComponentBuilder.
+     * Returns a {@link ScriptFileComponentBuilder} for creating a {@link 
ScriptFile} component.
+     * @param name the script file name
+     * @param path the script file path
+     * @return the new component builder instance
      */
-    AppenderComponentBuilder newAppender(String name, String pluginName);
+    ScriptFileComponentBuilder newScriptFile(@Nullable String name, @Nullable 
String path);
 
     /**
-     * Returns a builder for creating AppenderRefs.
-     * @param ref The name of the Appender being referenced.
-     * @return A new AppenderRefComponentBuilder.
+     * Returns a {@link AppenderComponentBuilder} for creating an {@link 
Appender} component.
+     * @param name the appender name
+     * @param pluginName the appender plugin-type
+     * @return the new component builder instance
      */
-    AppenderRefComponentBuilder newAppenderRef(String ref);
+    AppenderComponentBuilder newAppender(@Nullable String name, String 
pluginName);
 
     /**
-     * Returns a builder for creating Async Loggers.
-     * @param name The name of the Logger.
-     * @return A new LoggerComponentBuilder.
+     * Returns a {@link AppenderRefComponentBuilder} for creating an {@link 
AppenderRef} component.
+     * @param ref the name of the {@code Appender} being referenced
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newAsyncLogger(String name);
+    AppenderRefComponentBuilder newAppenderRef(@Nullable String ref);
 
     /**
-     * Returns a builder for creating Async Loggers.
-     * @param name The name of the Logger.
-     * @param includeLocation If true include location information.
-     * @return A new LoggerComponentBuilder.
+     * Returns a {@link LoggerComponentBuilder} builder for creating an {@link 
AsyncLogger} component.
+     * @param name the logger name
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newAsyncLogger(String name, boolean 
includeLocation);
+    LoggerComponentBuilder newAsyncLogger(@Nullable String name);
 
     /**
-     * Returns a builder for creating Async Loggers.
-     * @param name The name of the Logger.
-     * @param level The logging Level to be assigned to the Logger.
-     * @return A new LoggerComponentBuilder.
+     * Returns a {@link LoggerComponentBuilder} for creating an {@link 
AsyncLogger} component.
+     * @param name the logger name
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newAsyncLogger(String name, Level level);
+    LoggerComponentBuilder newAsyncLogger(@Nullable String name, boolean 
includeLocation);
 
     /**
-     * Returns a builder for creating Async Loggers.
+     * Returns a {@link LoggerComponentBuilder} for creating an {@link 
AsyncLogger} component.
      * @param name The name of the Logger.
      * @param level The logging Level to be assigned to the Logger.
-     * @param includeLocation If true include location information.
      * @return A new LoggerComponentBuilder.
      */
-    LoggerComponentBuilder newAsyncLogger(String name, Level level, boolean 
includeLocation);
+    LoggerComponentBuilder newAsyncLogger(@Nullable String name, @Nullable 
Level level);
 
     /**
-     * Returns a builder for creating Async Loggers.
-     * @param name The name of the Logger.
-     * @param level The logging Level to be assigned to the Logger.
-     * @return A new LoggerComponentBuilder.
+     * Returns a {@link LoggerComponentBuilder} for creating an {@link 
AsyncLogger} component.
+     * @param name the logger name
+     * @param level the logger level
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newAsyncLogger(String name, String level);
+    LoggerComponentBuilder newAsyncLogger(@Nullable String name, @Nullable 
Level level, boolean includeLocation);
 
     /**
-     * Returns a builder for creating Async Loggers.
-     * @param name The name of the Logger.
-     * @param level The logging Level to be assigned to the Logger.
-     * @param includeLocation If true include location information.
-     * @return A new LoggerComponentBuilder.
+     * Returns a {@link LoggerComponentBuilder} for creating an {@link 
AsyncLogger} component
+     * @param name the logger name
+     * @param level the logger level
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newAsyncLogger(String name, String level, boolean 
includeLocation);
+    LoggerComponentBuilder newAsyncLogger(@Nullable String name, @Nullable 
String level);
 
     /**
-     * Returns a builder for creating the async root Logger.
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a {@link LoggerComponentBuilder} for creating an {@link 
AsyncLogger} component.
+     * @param name the logger name
+     * @param level the logger level
+     * @param includeLocation {@code true} to include location inforrmation; 
otherwise, {@code false}
+     * @return the new component builder instance
+     */
+    LoggerComponentBuilder newAsyncLogger(@Nullable String name, @Nullable 
String level, boolean includeLocation);
+
+    /**
+     * Returns a {@link RootLoggerComponentBuilder} for creating a root {@link 
AsyncLogger} component.
+     * @return the new component builder instance
      */
     RootLoggerComponentBuilder newAsyncRootLogger();
 
     /**
-     * Returns a builder for creating the async root Logger.
-     * @param includeLocation If true include location information.
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a {@link RootLoggerComponentBuilder} for creating a root {@link 
AsyncLogger} component.
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instance
      */
     RootLoggerComponentBuilder newAsyncRootLogger(boolean includeLocation);
 
     /**
-     * Returns a builder for creating the async root Logger.
-     * @param level The logging Level to be assigned to the root Logger.
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a {@link RootLoggerComponentBuilder} for creating a root {@link 
AsyncLogger} component.
+     * @param level the logger level
+     * @return the new component builder instance
+     */
+    RootLoggerComponentBuilder newAsyncRootLogger(@Nullable Level level);
+
+    /**
+     * Returns a {@link RootLoggerComponentBuilder} for creating a root {@link 
AsyncLogger} component.
+     * @param level the logger level
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instance
      */
-    RootLoggerComponentBuilder newAsyncRootLogger(Level level);
+    RootLoggerComponentBuilder newAsyncRootLogger(@Nullable Level level, 
boolean includeLocation);
 
     /**
-     * Returns a builder for creating the async root Logger.
-     * @param level The logging Level to be assigned to the root Logger.
-     * @param includeLocation If true include location information.
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a {@link RootLoggerComponentBuilder} for creating a root {@link 
AsyncLogger} component.
+     * @param level the logger level
+     * @return the new component builder instance
      */
-    RootLoggerComponentBuilder newAsyncRootLogger(Level level, boolean 
includeLocation);
+    RootLoggerComponentBuilder newAsyncRootLogger(@Nullable String level);
 
     /**
-     * Returns a builder for creating the async root Logger.
-     * @param level The logging Level to be assigned to the root Logger.
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a {@link RootLoggerComponentBuilder} for creating a root {@link 
AsyncLogger} component.
+     * @param level the logger level
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instance
      */
-    RootLoggerComponentBuilder newAsyncRootLogger(String level);
+    RootLoggerComponentBuilder newAsyncRootLogger(@Nullable String level, 
boolean includeLocation);
 
     /**
-     * Returns a builder for creating the async root Logger.
-     * @param level The logging Level to be assigned to the root Logger.
-     * @param includeLocation If true include location information.
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a new {@link ComponentBuilder} for creating a generic {@link 
Component}.
+     * @param <B> the {@code ComponentBuilder} target type
+     * @param pluginType the component plugin type
+     * @return the new component builder instance
      */
-    RootLoggerComponentBuilder newAsyncRootLogger(String level, boolean 
includeLocation);
+    <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(String 
pluginType);
 
     /**
-     * Returns a builder for creating generic components.
-     * @param <B> ComponentBuilder target type
-     * @param pluginName The Plugin type of the component.
-     * @return A new ComponentBuilder.
+     * Returns a new {@link ComponentBuilder} for creating a generic {@link 
Component}.
+     * @param <B> the {@code ComponentBuilder} target type
+     * @param name the component name
+     * @param pluginType the component plugin type
+     * @return the new component builder instance
      */
-    <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(String 
pluginName);
+    <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(@Nullable 
String name, String pluginType);
 
     /**
-     * Returns a builder for creating generic components.
-     * @param <B> ComponentBuilder target type
-     * @param name The name of the component (may be null).
-     * @param pluginName The Plugin type of the component.
-     * @return A new ComponentBuilder.
+     * Returns a new {@link ComponentBuilder} for creating a generic {@link 
Component}.
+     * @param <B> the {@code ComponentBuilder} target type
+     * @param name the component name
+     * @param pluginType the component plugin type
+     * @param value the component value
+     * @return the new component builder instance
      */
-    <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(String 
name, String pluginName);
+    <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(
+            @Nullable String name, String pluginType, @Nullable String value);
 
     /**
-     * Returns a builder for creating generic components.
-     * @param <B> ComponentBuilder target type
-     * @param name The name of the component (may be null).
-     * @param pluginName The Plugin type of the component.
-     * @param value The value of the component.
-     * @return A new ComponentBuilder.
+     * Returns a new {@link PropertyComponentBuilder} for creating a {@link 
Property} component.
+     * @param name the property name
+     * @param value the property value
+     * @return the new component builder instance
      */
-    <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(String 
name, String pluginName, String value);
+    PropertyComponentBuilder newProperty(@Nullable String name, @Nullable 
String value);
 
     /**
-     * Returns a builder for creating Property:s
-     * @param name The name of the property.
-     * @param value The value of the component.
-     * @return A new PropertyComponentBuilder.
+     * Returns a new {@link PropertyComponentBuilder} for creating a {@link 
KeyValuePair} component.
+     * @param key the key
+     * @param value the value
+     * @return the new component builder instance
      */
-    PropertyComponentBuilder newProperty(String name, String value);
+    KeyValuePairComponentBuilder newKeyValuePair(@Nullable String key, 
@Nullable String value);
 
     /**
-     * Returns a builder for creating KeyValuePair:s
-     * @param key The name
-     * @param value The value
-     * @return A new KeyValuePairComponentBuilder.
+     * Returns a new {@link CustomLevelComponentBuilder} for creating a {@link 
CustomLevels} component.
+     * @param name the custom level name
+     * @param intLevel the integer value to be assigned to the level
+     * @return the new component builder instance
      */
-    KeyValuePairComponentBuilder newKeyValuePair(String key, String value);
+    CustomLevelComponentBuilder newCustomLevel(@Nullable String name, int 
intLevel);
 
     /**
-     * Returns a builder for creating CustomLevels
-     * @param name The name of the custom level.
-     * @param level The integer value to be assigned to the level.
-     * @return A new CustomLevelComponentBuilder.
+     * Returns a new {@link FilterComponentBuilder} for creating a {@link 
Filter} component.
+     * @param pluginType the plugin type of the filter
+     * @return the new component builder instance
      */
-    CustomLevelComponentBuilder newCustomLevel(String name, int level);
+    FilterComponentBuilder newFilter(String pluginType);
 
     /**
-     * Returns a builder for creating Filters.
-     * @param pluginName The Plugin type of the Filter.
+     * Returns a new {@link FilterComponentBuilder} for creating a {@code 
Filter} component.
+     * @param pluginType The Plugin type of the Filter.
      * @param onMatch "ACCEPT", "DENY", or "NEUTRAL"
      * @param onMismatch "ACCEPT", "DENY", or "NEUTRAL"
-     * @return A new FilterComponentBuilder.
+     * @return the new component builder instance
      */
-    FilterComponentBuilder newFilter(String pluginName, Filter.Result onMatch, 
Filter.Result onMismatch);
+    FilterComponentBuilder newFilter(String pluginType, @Nullable Result 
onMatch, @Nullable Result onMismatch);
 
     /**
-     * Returns a builder for creating Filters.
-     * @param pluginName The Plugin type of the Filter.
+     * Returns a new {@link FilterComponentBuilder} for creating a {@link 
Filter} component.
+     * @param pluginType the plugin type of the filter
      * @param onMatch "ACCEPT", "DENY", or "NEUTRAL"
      * @param onMismatch "ACCEPT", "DENY", or "NEUTRAL"
-     * @return A new FilterComponentBuilder.
+     * @return the new component builder instance
      */
-    FilterComponentBuilder newFilter(String pluginName, String onMatch, String 
onMismatch);
+    FilterComponentBuilder newFilter(String pluginType, @Nullable String 
onMatch, @Nullable String onMismatch);
 
     /**
-     * Returns a builder for creating Layouts.
-     * @param pluginName The Plugin type of the Layout.
-     * @return A new LayoutComponentBuilder.
+     * Returns a new {@link LayoutComponentBuilder} for creating a {@link 
Layout} component.
+     * @param pluginType the plugin type of the layout
+     * @return the new component builder instance
      */
-    LayoutComponentBuilder newLayout(String pluginName);
+    LayoutComponentBuilder newLayout(String pluginType);
 
     /**
-     * Returns a builder for creating Loggers.
-     * @param name The name of the Logger.
-     * @return A new LoggerComponentBuilder.
+     * Returns a new {@link LayoutComponentBuilder} for creating a {@link 
Layout} component.
+     * @param name the logger name
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newLogger(String name);
+    LoggerComponentBuilder newLogger(@Nullable String name);
 
     /**
-     * Returns a builder for creating Loggers.
-     * @param name The name of the Logger.
-     * @param includeLocation If true include location information.
-     * @return A new LoggerComponentBuilder.
+     * Returns a new {@link LoggerComponentBuilder} for creating a {@link 
Logger} component.
+     * @param name the logger name
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newLogger(String name, boolean includeLocation);
+    LoggerComponentBuilder newLogger(@Nullable String name, boolean 
includeLocation);
 
     /**
-     * Returns a builder for creating Loggers.
-     * @param name The name of the Logger.
-     * @param level The logging Level to be assigned to the Logger.
-     * @return A new LoggerComponentBuilder.
+     * Returns a new {@link LoggerComponentBuilder} for creating a {@link 
Logger} component.
+     * @param name the logger name
+     * @param level the logger level
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newLogger(String name, Level level);
+    LoggerComponentBuilder newLogger(@Nullable String name, @Nullable Level 
level);
 
     /**
-     * Returns a builder for creating Loggers.
-     * @param name The name of the Logger.
-     * @param level The logging Level to be assigned to the Logger.
-     * @param includeLocation If true include location information.
-     * @return A new LoggerComponentBuilder.
+     * Returns a new {@link LoggerComponentBuilder} for creating a {@link 
Logger} component.
+     * @param name the logger name
+     * @param level the logger level
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newLogger(String name, Level level, boolean 
includeLocation);
+    LoggerComponentBuilder newLogger(@Nullable String name, @Nullable Level 
level, boolean includeLocation);
 
     /**
-     * Returns a builder for creating Loggers.
-     * @param name The name of the Logger.
-     * @param level The logging Level to be assigned to the Logger.
-     * @return A new LoggerComponentBuilder.
+     * Returns a new {@link LoggerComponentBuilder} for creating a {@link 
Logger} component.
+     * @param name the logger name
+     * @param level the logger level
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newLogger(String name, String level);
+    LoggerComponentBuilder newLogger(@Nullable String name, @Nullable String 
level);
 
     /**
-     * Returns a builder for creating Loggers.
-     * @param name The name of the Logger.
-     * @param level The logging Level to be assigned to the Logger.
-     * @param includeLocation If true include location information.
-     * @return A new LoggerComponentBuilder.
+     * Returns a new {@link LoggerComponentBuilder} for creating a {@link 
Logger} component.
+     * @param name the logger name
+     * @param level the logger level
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instance
      */
-    LoggerComponentBuilder newLogger(String name, String level, boolean 
includeLocation);
+    LoggerComponentBuilder newLogger(@Nullable String name, @Nullable String 
level, boolean includeLocation);
 
     /**
-     * Returns a builder for creating the root Logger.
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a new {@link RootLoggerComponentBuilder} for creating a {@link 
RootLogger} component.
+     * @return the new component builder instance
      */
     RootLoggerComponentBuilder newRootLogger();
 
     /**
-     * Returns a builder for creating the root Logger.
-     * @param includeLocation If true include location information.
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a new {@link RootLoggerComponentBuilder} for creating a {@link 
RootLogger} component.
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instancec
      */
     RootLoggerComponentBuilder newRootLogger(boolean includeLocation);
 
     /**
-     * Returns a builder for creating the root Logger.
-     * @param level The logging Level to be assigned to the root Logger.
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a new {@link RootLoggerComponentBuilder} for creating a {@link 
RootLogger} component.
+     * @param level the logger level
+     * @return the new component builder instance
      */
-    RootLoggerComponentBuilder newRootLogger(Level level);
+    RootLoggerComponentBuilder newRootLogger(@Nullable Level level);
 
     /**
-     * Returns a builder for creating the root Logger.
-     * @param level The logging Level to be assigned to the root Logger.
-     * @param includeLocation If true include location information.
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a new {@link RootLoggerComponentBuilder} for creating a {@link 
RootLogger} component.
+     * @param level the logger level
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instance
      */
-    RootLoggerComponentBuilder newRootLogger(Level level, boolean 
includeLocation);
+    RootLoggerComponentBuilder newRootLogger(@Nullable Level level, boolean 
includeLocation);
 
     /**
-     * Returns a builder for creating the root Logger.
-     * @param level The logging Level to be assigned to the root Logger.
-     *
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a new {@link RootLoggerComponentBuilder} for creating a {@link 
RootLogger} component.
+     * @param level the logger level
+     * @return the new component builder instance
      */
-    RootLoggerComponentBuilder newRootLogger(String level);
+    RootLoggerComponentBuilder newRootLogger(@Nullable String level);
 
     /**
-     * Returns a builder for creating the root Logger.
-     * @param level The logging Level to be assigned to the root Logger.
-     *
-     * @return A new RootLoggerComponentBuilder.
+     * Returns a new {@link RootLoggerComponentBuilder} for creating a {@link 
RootLogger} component.
+     * @param level the logger level
+     * @param includeLocation {@code true} to include location information; 
otherwise, {@code false}
+     * @return the new component builder instance
      */
-    RootLoggerComponentBuilder newRootLogger(String level, boolean 
includeLocation);
+    RootLoggerComponentBuilder newRootLogger(@Nullable String level, boolean 
includeLocation);
 
     /**
      * Set the Advertiser Plugin name.
      * @param advertiser The Advertiser Plugin name.
      * @return this builder instance.
      */
-    ConfigurationBuilder<T> setAdvertiser(String advertiser);
+    ConfigurationBuilder<T> setAdvertiser(@Nullable String advertiser);
 
     /**
      * Sets the name of the configuration.
      * @param name the name of the {@link Configuration}. By default is {@code 
"Constructed"}.
      * @return this builder instance.
      */
-    ConfigurationBuilder<T> setConfigurationName(String name);
+    ConfigurationBuilder<T> setConfigurationName(@Nullable String name);
 
     /**
-     * Sets the configuration source, if one exists.
-     * @param configurationSource the ConfigurationSource.
-     * @return this builder instance.
+     * Sets the configuration source.
+     * @param configurationSource the configuration source
+     * @return this builder instance (for chaining)
      */
-    ConfigurationBuilder<T> setConfigurationSource(ConfigurationSource 
configurationSource);
+    ConfigurationBuilder<T> setConfigurationSource(@Nullable 
ConfigurationSource configurationSource);
 
     /**
-     * Sets the interval at which the configuration file should be checked for 
changes.
-     * @param intervalSeconds The number of seconds that should pass between 
checks of the configuration file.
+     * Specifies the destination for StatusLogger events. This can be {@code 
out} (default) for using
+     * {@link System#out standard out}, {@code err} for using {@link 
System#err standard error}, or a file URI to
+     * which log events will be written. If the provided URI is invalid, then 
the default destination of standard
+     * out will be used.
+     *
+     * @param destination where status log messages should be output.
      * @return this builder instance.
      */
-    ConfigurationBuilder<T> setMonitorInterval(String intervalSeconds);
+    ConfigurationBuilder<T> setDestination(@Nullable String destination);
 
     /**
-     * Sets the list of packages to search for plugins.
-     * @param packages The comma separated list of packages.
-     * @return this builder instance.
+     * Sets the logger context.
+     * @param loggerContext the logger context.
      */
-    ConfigurationBuilder<T> setPackages(String packages);
+    @BaselineIgnore("2.25.0")
+    ConfigurationBuilder<T> setLoggerContext(@Nullable LoggerContext 
loggerContext);
 
     /**
-     * Sets whether the shutdown hook should be disabled.
-     * @param flag "disable" will prevent the shutdown hook from being set.
-     * @return this builder instance.
+     * Sets the configuration's "monitorInterval" attribute.
+     * <p>
+     *   The monitor interval specifies the number of seconds between checks 
for changes to the configuration source.
+     * </p>
+     * @param intervalSeconds the number of seconds that should pass between 
checks of the configuration source
+     * @return this builder instance
      */
-    ConfigurationBuilder<T> setShutdownHook(String flag);
+    ConfigurationBuilder<T> setMonitorInterval(int intervalSeconds);
 
     /**
-     * How long appenders and background tasks will get to shutdown when the 
JVM shuts down.
-     * Default is zero which mean that each appender uses its default timeout, 
and don't wait for background
-     * tasks. Not all appenders will honor this, it is a hint and not an 
absolute guarantee that the shutdown
-     * procedure will not take longer. Setting this too low increase the risk 
of losing outstanding log events
-     * not yet written to the final destination. (Not used if {@link 
#setShutdownHook(String)} is set to "disable".)
-     * @return this builder instance.
+     * Sets the configuration's "monitorInterval" attribute.
+     * <p>
+     *   The monitor interval specifies the number of seconds between checks 
for changes to the configuration source.
+     * </p>
+     * @param intervalSeconds the number of seconds that should pass between 
checks of the configuration source
+     * @return this builder instance
+     * @throws NumberFormatException if the {@code intervalSeconds} argument 
is not a valid integer representation
+     */
+    ConfigurationBuilder<T> setMonitorInterval(String intervalSeconds);
+
+    /**
+     * Sets the configuration's list of packages to search for Log4j plugins.
+     * @param packages a comma separated list of packages
+     * @return this builder (for chaining)
+     */
+    ConfigurationBuilder<T> setPackages(@Nullable String packages);

Review Comment:
   This is deprecated and we could mark it as such.



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultComponentBuilder.java:
##########
@@ -17,104 +17,217 @@
 package org.apache.logging.log4j.core.config.builder.impl;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.builder.api.Component;
 import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
+import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
 
 /**
- * Generic component that captures attributes and Components in preparation 
for assembling the Appender's
- * Component.
+ * Generic base default {@link ComponentBuilder} implementation that captures 
attributes and children
+ * which are used to build a new {@link Component} instance.
  *
+ * @param <T> the type of the component builder
+ * @param <CB> the type of the configuration builder
  * @since 2.4
  */
+@ProviderType
 class DefaultComponentBuilder<T extends ComponentBuilder<T>, CB extends 
ConfigurationBuilder<? extends Configuration>>
         implements ComponentBuilder<T> {
 
     private final CB builder;
-    private final String type;
+    private final String pluginType;
     private final Map<String, String> attributes = new LinkedHashMap<>();
     private final List<Component> components = new ArrayList<>();
-    private final String name;
-    private final String value;
-
-    public DefaultComponentBuilder(final CB builder, final String type) {
-        this(builder, null, type, null);
+    private final @Nullable String name;
+    private final @Nullable String value;
+
+    /**
+     * Constructs a new instance with the given configuration builder and 
plugin-type with {@code null} name and value.
+     * @param builder the configuration builder
+     * @param pluginType the plugin-type of the component being built
+     * @throws NullPointerException if either {@code builder} or {@code type} 
argument is null
+     */
+    public DefaultComponentBuilder(final CB builder, final String pluginType) {
+        this(builder, pluginType, null, null);
     }
 
-    public DefaultComponentBuilder(final CB builder, final String name, final 
String type) {
-        this(builder, name, type, null);
+    /**
+     * Constructs a new instancer with the given configuration builder, 
plugin-type, name, and {@code null} value.
+     * @param builder the configuration builder
+     * @param pluginType the plugin-type of the component being built
+     * @param name the component name
+     * @throws NullPointerException if either {@code builder} or {@code type} 
argument is null
+     */
+    public DefaultComponentBuilder(final CB builder, final String pluginType, 
final @Nullable String name) {
+        this(builder, pluginType, name, null);
     }
 
-    public DefaultComponentBuilder(final CB builder, final String name, final 
String type, final String value) {
-        this.type = type;
-        this.builder = builder;
+    /**
+     * Constructs a new instance with the given configuration builder, 
plugin-type, name and value.
+     * @param builder the configuration builder
+     * @param pluginType the type (plugin-type) of the component being built
+     * @param name the component name
+     * @param value the component value
+     * @throws NullPointerException if either {@code builder} or {@code type} 
argument is null
+     */
+    public DefaultComponentBuilder(
+            final CB builder, final String pluginType, final @Nullable String 
name, final @Nullable String value) {
+        super();
+        this.builder = Objects.requireNonNull(builder, "The 'builder' argument 
must not be null.");
+        this.pluginType = Objects.requireNonNull(pluginType, "The 'type' 
argument must not be null.");
         this.name = name;
         this.value = value;
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final boolean value) {
-        return put(key, Boolean.toString(value));
+    public Component build() {
+        final Component component = new Component(pluginType, name, value);
+        component.getAttributes().putAll(attributes);
+        component.getComponents().addAll(components);
+        return component;
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final Enum<?> value) {
-        return put(key, value.name());
+    public T addComponent(final ComponentBuilder<?> builder) {
+        Objects.requireNonNull(builder, "The 'builder' argument must not be 
null.");
+        components.add(builder.build());
+        return self();
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final int value) {
-        return put(key, Integer.toString(value));
+    public @NonNull CB getBuilder() {
+        return builder;
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final Level level) {
-        return put(key, level.toString());
+    public @Nullable String getName() {
+        return name;
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final Object value) {
-        return put(key, value.toString());
+    public T setAttribute(final String key, final boolean value) {
+        return putAttribute(key, Boolean.toString(value));
     }
 
+    /** {@inheritDoc} */
     @Override
-    public T addAttribute(final String key, final String value) {
-        return put(key, value);
+    public T setAttribute(final String key, final int value) {
+        return putAttribute(key, Integer.toString(value));
     }
 
+    /** {@inheritDoc} */
     @Override
-    @SuppressWarnings("unchecked")
-    public T addComponent(final ComponentBuilder<?> builder) {
-        components.add(builder.build());
-        return (T) this;
+    public T setAttribute(final String key, final @Nullable Enum<?> value) {
+        return putAttribute(key, (value != null) ? value.name() : null);
     }
 
+    /** {@inheritDoc} */
     @Override
-    public Component build() {
-        final Component component = new Component(type, name, value);
-        component.getAttributes().putAll(attributes);
-        component.getComponents().addAll(components);
-        return component;
+    public T setAttribute(final String key, final @Nullable Level level) {
+        return putAttribute(key, (level != null) ? level.toString() : null);
     }
 
+    /** {@inheritDoc} */
     @Override
-    public CB getBuilder() {
-        return builder;
+    public T setAttribute(final String key, final @Nullable Object value) {
+        return putAttribute(key, Objects.toString(value, null));
     }
 
+    /** {@inheritDoc} */
     @Override
-    public String getName() {
-        return name;
+    public T setAttribute(final String key, final @Nullable String value) {
+        return putAttribute(key, value);
+    }
+
+    /**
+     * Clears the internal state removing all configured attributes and 
components.
+     * <p>
+     *   This method is primarily intended to be used in testing.
+     * </p>
+     */
+    protected void clear() {
+        synchronized (this) {
+            attributes.clear();
+            components.clear();
+        }
+    }
+
+    /**
+     * Gets the value of the component attribute with the given key.
+     *
+     * @param key the key
+     * @return the attribute value or {@code null} if not found
+     */
+    protected @Nullable String getAttribute(final @NonNull String key) {
+
+        Objects.requireNonNull(key, "The 'key' argument must not be null.");
+
+        return this.attributes.get(key);
+    }
+
+    /**
+     * Gets the map of key/value component attributes.
+     * <p>
+     *   The result map is guaranteed to have both non-{@code null} keys and 
values.
+     * </p>
+     * @return an <i>immutable</i> map of the key/value attributes
+     */
+    protected Map<String, String> getAttributes() {
+        return Collections.unmodifiableMap(attributes);
+    }
+
+    /**
+     * Gets the list of child components.
+     * @return an <i>immutable</i> list of the child components
+     */
+    protected List<Component> getComponents() {

Review Comment:
   ```suggestion
       protected List<? extends Component> getComponents() {
   ```
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@logging.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to