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

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


The following commit(s) were added to refs/heads/master by this push:
     new 5370298  LOG4J2-3307 - Move scripting to its own module
5370298 is described below

commit 5370298f3a549a3502a585e2de997a97101e651a
Author: Ralph Goers <[email protected]>
AuthorDate: Sat Jan 1 21:03:42 2022 -0700

    LOG4J2-3307 - Move scripting to its own module
---
 log4j-api/src/main/java/module-info.java           |   2 +-
 .../apache/logging/log4j/util/ProviderUtil.java    |  23 +-
 .../logging/log4j/util/ServiceLoaderUtil.java      |  69 ++++++
 log4j-core-test/pom.xml                            |  26 --
 .../rolling/action/DummyFileAttributes.java        |   2 +-
 log4j-core-test/src/main/java9/module-info.java    |   1 +
 .../rolling/action/IfAccumulatedFileSizeTest.java  |   1 +
 .../rolling/action/IfLastModifiedTest.java         |   1 +
 .../action/PathSortByModificationTimeTest.java     |   1 +
 .../log4j/core/config/TestConfigurator.java        |  39 +--
 log4j-core-test/src/test/java9/module-info.java    |   1 -
 log4j-core/src/main/java/module-info.java          |  35 +--
 .../core/appender/rolling/action/DeleteAction.java |   7 +-
 .../log4j/core/appender/routing/Routes.java        |  18 +-
 .../core/appender/routing/RoutingAppender.java     |  18 +-
 .../log4j/core/config/AbstractConfiguration.java   |  20 +-
 .../core/config/plugins/util/PluginBuilder.java    |   9 +-
 .../apache/logging/log4j/core/script/Script.java   |  43 +---
 .../{package-info.java => ScriptBindings.java}     |  11 +-
 .../{package-info.java => ScriptConditional.java}  |  13 +-
 .../logging/log4j/core/script/ScriptManager.java   | 270 +--------------------
 ...package-info.java => ScriptManagerFactory.java} |  12 +-
 log4j-jpl/pom.xml                                  |   7 +-
 log4j-jpl/src/main/java/module-info.java           |   1 +
 log4j-plugins/src/main/java/module-info.java       |   3 +-
 .../logging/log4j/plugins/util/PluginRegistry.java |  12 +-
 .../logging/log4j/plugins/util/PluginType.java     |   4 +
 .../log4j/plugins/validation/PluginValidator.java  |  21 +-
 .../validation/constraints/RequiredClass.java      |  49 ++++
 .../validation/constraints/RequiredProperty.java   |  51 ++++
 .../validators/RequiredClassValidator.java         |  61 +++++
 .../validators/RequiredPropertyValidator.java      |  65 +++++
 log4j-script/pom.xml                               |  27 +++
 log4j-script/src/main/java/module-info.java        |  36 +++
 .../logging/log4j}/script/AbstractScript.java      |   4 +-
 .../apache/logging/log4j}/script/ScriptFile.java   |   2 +-
 .../logging/log4j/script/ScriptManagerImpl.java    |  70 ++++--
 .../apache/logging/log4j/script/ScriptPlugin.java  |  12 +-
 .../apache/logging/log4j}/script/ScriptRef.java    |   8 +-
 .../logging/log4j/script}/ScriptsPlugin.java       |   3 +-
 .../script}/appender/ScriptAppenderSelector.java   |  26 +-
 .../appender/rolling/action/ScriptCondition.java   |  21 +-
 .../script/config/arbiter}/ScriptArbiter.java      |  23 +-
 .../script/factory/ScriptManagerFactoryImpl.java   |  19 +-
 .../logging/log4j/script}/filter/ScriptFilter.java |  28 ++-
 .../script}/layout/ScriptPatternSelector.java      |  13 +-
 .../apache/logging/log4j}/script/package-info.java |   2 +-
 ....logging.log4j.core.script.ScriptManagerFactory |   1 +
 .../appender/ScriptAppenderSelectorTest.java       |   2 +-
 .../RollingAppenderDeleteScriptFri13thTest.java    |   2 +-
 .../rolling/RollingAppenderDeleteScriptTest.java   |   2 +-
 .../rolling/action/ScriptConditionTest.java        |  16 +-
 .../routing/DefaultRouteScriptAppenderTest.java    |   3 +-
 .../appender/routing/RoutesScriptAppenderTest.java |  12 +-
 .../log4j/script/config/TestConfigurator.java      |  79 ++++++
 .../script/config/arbiter}/ScriptArbiterTest.java  |   2 +-
 .../script}/filter/AbstractScriptFilterTest.java   |   2 +-
 .../filter/ScriptFileFilterPropertiesTest.java     |   2 +-
 .../log4j/script}/filter/ScriptFileFilterTest.java |   2 +-
 .../log4j/script}/filter/ScriptFilterTest.java     |   2 +-
 .../log4j/script}/filter/ScriptRefFilterTest.java  |   2 +-
 .../log4j/script/layout}/PatternSelectorTest.java  |  12 +-
 .../resources/log4j-appender-selector-groovy.xml   |   0
 .../log4j-appender-selector-javascript.xml         |   0
 .../src/test/resources/log4j-patternSelector.xml   |   0
 ...j-rolling-with-custom-delete-script-fri13th.xml |   0
 .../log4j-rolling-with-custom-delete-script.xml    |   0
 .../log4j-routing-default-route-script-groovy.xml  |   0
 ...g4j-routing-default-route-script-javascript.xml |   0
 .../log4j-routing-routes-script-groovy.xml         |   0
 .../log4j-routing-routes-script-javascript.xml     |   0
 .../log4j-routing-script-staticvars-groovy.xml     |   0
 .../log4j-routing-script-staticvars-javascript.xml |   0
 .../src/test/resources/log4j-script-filters.xml    |   0
 .../resources/log4j-scriptFile-filters.properties  |   0
 .../test/resources/log4j-scriptFile-filters.xml    |   0
 .../src/test/resources/log4j-scriptRef-filters.xml |   0
 .../src/test/resources/log4j2-scriptArbiters.xml   |   0
 .../src/test/resources/scripts/filter.groovy       |   2 +
 .../src/test/resources/scripts/filter.js           |   0
 pom.xml                                            |   1 +
 src/changes/changes.xml                            |   3 +
 src/site/asciidoc/manual/appenders.adoc            |   2 +-
 src/site/asciidoc/manual/filters.adoc              |   2 +-
 84 files changed, 777 insertions(+), 564 deletions(-)

diff --git a/log4j-api/src/main/java/module-info.java 
b/log4j-api/src/main/java/module-info.java
index b74edd7..d2c9490 100644
--- a/log4j-api/src/main/java/module-info.java
+++ b/log4j-api/src/main/java/module-info.java
@@ -22,7 +22,7 @@ module org.apache.logging.log4j {
     exports org.apache.logging.log4j.status;
     exports org.apache.logging.log4j.util;
 
-    requires transitive org.osgi.framework;
+    requires static org.osgi.framework;
     uses org.apache.logging.log4j.spi.Provider;
     uses org.apache.logging.log4j.util.PropertySource;
     uses org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory;
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java 
b/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java
index 0a01886..5651dcd 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java
@@ -62,13 +62,9 @@ public final class ProviderUtil {
     private static volatile ProviderUtil instance;
 
     private ProviderUtil() {
-        for (final ClassLoader classLoader : LoaderUtil.getClassLoaders()) {
-            try {
-                loadProviders(classLoader);
-            } catch (final Throwable ex) {
-                LOGGER.debug("Unable to retrieve provider from ClassLoader 
{}", classLoader, ex);
-            }
-        }
+        PROVIDERS.addAll(ServiceLoaderUtil.loadServices(Provider.class,
+                (layer) -> ServiceLoader.load(layer, Provider.class),
+                (provider) -> validVersion(provider.getVersions())));
         for (final LoaderUtil.UrlResource resource : 
LoaderUtil.findUrlResources(PROVIDER_RESOURCE)) {
             loadProvider(resource.getUrl(), resource.getClassLoader());
         }
@@ -99,19 +95,6 @@ public final class ProviderUtil {
         }
     }
 
-    /**
-     * 
-     * @param classLoader null can be used to mark the bootstrap class loader.
-     */
-    protected static void loadProviders(final ClassLoader classLoader) {
-        final ServiceLoader<Provider> serviceLoader = 
ServiceLoader.load(Provider.class, classLoader);
-        for (final Provider provider : serviceLoader) {
-            if (validVersion(provider.getVersions()) && 
!PROVIDERS.contains(provider)) {
-                PROVIDERS.add(provider);
-            }
-        }
-    }
-
     public static Iterable<Provider> getProviders() {
         lazyInit();
         return PROVIDERS;
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java 
b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
new file mode 100644
index 0000000..785291b
--- /dev/null
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.function.Function;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.status.StatusLogger;
+
+/**
+ * Loads all valid instances of a service.
+ */
+public class ServiceLoaderUtil {
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    public static <S> List<S> loadServices(final Class<S> clazz, 
Function<ModuleLayer, ServiceLoader<S>> loader,
+            Function<S, Boolean> validator) {
+        final List<S> services = new ArrayList<>();
+        final ModuleLayer moduleLayer = 
ServiceLoaderUtil.class.getModule().getLayer();
+        if (moduleLayer == null) {
+            final ClassLoader[] classLoaders = LoaderUtil.getClassLoaders();
+            Throwable throwable = null;
+            ClassLoader errorClassLoader = null;
+            for (ClassLoader classLoader : classLoaders) {
+                try {
+                    final ServiceLoader<S> serviceLoader = 
ServiceLoader.load(clazz, classLoader);
+                    for (final S service : serviceLoader) {
+                        if (!services.contains(service) && (validator == null 
|| validator.apply(service))) {
+                            services.add(service);
+                        }
+                    }
+                } catch (final Throwable ex) {
+                    if (throwable == null) {
+                        throwable = ex;
+                        errorClassLoader = classLoader;
+                    }
+                }
+            }
+            if (services.size() == 0 && throwable != null) {
+                LOGGER.debug("Unable to retrieve provider from ClassLoader 
{}", errorClassLoader, throwable);
+            }
+        } else {
+            final ServiceLoader<S> serviceLoader = loader.apply(moduleLayer);
+            for (final S service : serviceLoader) {
+                if (!services.contains(service) && (validator == null || 
validator.apply(service))) {
+                    services.add(service);
+                }
+            }
+        }
+        return services;
+    }
+}
diff --git a/log4j-core-test/pom.xml b/log4j-core-test/pom.xml
index a580e32..1b28951 100644
--- a/log4j-core-test/pom.xml
+++ b/log4j-core-test/pom.xml
@@ -262,38 +262,12 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache-extras.beanshell</groupId>
-      <artifactId>bsh</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
       <groupId>org.graalvm.truffle</groupId>
       <artifactId>truffle-api</artifactId>
       <version>21.3.0</version>
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.openjdk.nashorn</groupId>
-      <artifactId>nashorn-core</artifactId>
-      <version>15.3</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.groovy</groupId>
-      <artifactId>groovy</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.groovy</groupId>
-      <artifactId>groovy-jsr223</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.groovy</groupId>
-      <artifactId>groovy-dateutil</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
       <groupId>org.hdrhistogram</groupId>
       <artifactId>HdrHistogram</artifactId>
       <scope>test</scope>
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/DummyFileAttributes.java
 
b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/appender/rolling/action/DummyFileAttributes.java
similarity index 96%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/DummyFileAttributes.java
rename to 
log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/appender/rolling/action/DummyFileAttributes.java
index c2bbb1b..9c14230 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/DummyFileAttributes.java
+++ 
b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/appender/rolling/action/DummyFileAttributes.java
@@ -15,7 +15,7 @@
  * limitations under the license.
  */
 
-package org.apache.logging.log4j.core.appender.rolling.action;
+package org.apache.logging.log4j.core.test.appender.rolling.action;
 
 import java.nio.file.attribute.BasicFileAttributes;
 import java.nio.file.attribute.FileTime;
diff --git a/log4j-core-test/src/main/java9/module-info.java 
b/log4j-core-test/src/main/java9/module-info.java
index 1479ae2..f84c4ac 100644
--- a/log4j-core-test/src/main/java9/module-info.java
+++ b/log4j-core-test/src/main/java9/module-info.java
@@ -17,6 +17,7 @@
 module org.apache.logging.log4j.core.test {
     exports org.apache.logging.log4j.core.test;
     exports org.apache.logging.log4j.core.test.appender;
+    exports org.apache.logging.log4j.core.test.appender.rolling.action;
     exports org.apache.logging.log4j.core.test.categories;
     exports org.apache.logging.log4j.core.test.hamcrest;
     exports org.apache.logging.log4j.core.test.junit;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/IfAccumulatedFileSizeTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/IfAccumulatedFileSizeTest.java
index 76bb0fc..70ff7ba 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/IfAccumulatedFileSizeTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/IfAccumulatedFileSizeTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.logging.log4j.core.appender.rolling.action;
 
+import 
org.apache.logging.log4j.core.test.appender.rolling.action.DummyFileAttributes;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/IfLastModifiedTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/IfLastModifiedTest.java
index b6f177c..21a29a7 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/IfLastModifiedTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/IfLastModifiedTest.java
@@ -19,6 +19,7 @@ package org.apache.logging.log4j.core.appender.rolling.action;
 
 import java.nio.file.attribute.FileTime;
 
+import 
org.apache.logging.log4j.core.test.appender.rolling.action.DummyFileAttributes;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTimeTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTimeTest.java
index 3893378..84afb62 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTimeTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTimeTest.java
@@ -21,6 +21,7 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.attribute.FileTime;
 
+import 
org.apache.logging.log4j.core.test.appender.rolling.action.DummyFileAttributes;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
index c592236..7b16ff6 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
@@ -443,43 +443,6 @@ public class TestConfigurator {
 
     }
 
-    @Test
-    public void testBuilderWithScripts() throws Exception {
-        final String script = "if 
(logEvent.getLoggerName().equals(\"NoLocation\")) {\n" +
-                "                return \"NoLocation\";\n" +
-                "            } else if (logEvent.getMarker() != null && 
logEvent.getMarker().isInstanceOf(\"FLOW\")) {\n" +
-                "                return \"Flow\";\n" +
-                "            } else {\n" +
-                "                return null;\n" +
-                "            }";
-        final ConfigurationBuilder<BuiltConfiguration> builder = 
ConfigurationBuilderFactory.newConfigurationBuilder();
-        builder.setStatusLevel(Level.ERROR);
-        builder.setConfigurationName("BuilderTest");
-        builder.add(builder.newScriptFile("filter.groovy", 
"target/test-classes/scripts/filter.groovy").addIsWatched(true));
-        final AppenderComponentBuilder appenderBuilder = 
builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
-                ConsoleAppender.Target.SYSTEM_OUT);
-        appenderBuilder.add(builder.newLayout("PatternLayout").
-                addComponent(builder.newComponent("ScriptPatternSelector")
-                        .addAttribute("defaultPattern", "[%-5level] %c{1.} 
%C{1.}.%M.%L %msg%n")
-                        
.addComponent(builder.newComponent("PatternMatch").addAttribute("key", 
"NoLocation")
-                                .addAttribute("pattern", "[%-5level] %c{1.} 
%msg%n"))
-                        
.addComponent(builder.newComponent("PatternMatch").addAttribute("key", "FLOW")
-                                .addAttribute("pattern", "[%-5level] %c{1.} 
====== %C{1.}.%M:%L %msg ======%n"))
-                        .addComponent(builder.newComponent("selectorScript", 
"Script", script).addAttribute("language", "beanshell"))));
-        appenderBuilder.add(builder.newFilter("ScriptFilter", 
Filter.Result.DENY,
-                
Filter.Result.NEUTRAL).addComponent(builder.newComponent("ScriptRef").addAttribute("ref",
 "filter.groovy")));
-        builder.add(appenderBuilder);
-        builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG).
-                add(builder.newAppenderRef("Stdout")).
-                addAttribute("additivity", false));
-        
builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
-        ctx = Configurator.initialize(builder.build());
-        final Configuration config = ctx.getConfiguration();
-        assertNotNull(config, "No configuration");
-        assertEquals("BuilderTest", config.getName(), "Unexpected 
Configuration");
-        assertThat(config.getAppenders(), hasSize(equalTo(1)));
-        assertNotNull(config.getScriptManager().getScript("filter.groovy"), 
"Filter script not found");
-        assertNotNull(config.getScriptManager().getScript("selectorScript"), 
"pattern selector script not found");
-    }
+
 
 }
diff --git a/log4j-core-test/src/test/java9/module-info.java 
b/log4j-core-test/src/test/java9/module-info.java
index d02fec4..03a6eac 100644
--- a/log4j-core-test/src/test/java9/module-info.java
+++ b/log4j-core-test/src/test/java9/module-info.java
@@ -60,7 +60,6 @@ open module org.apache.logging.log4j.core {
     requires transitive java.management;
     requires transitive java.sql;
     requires transitive java.rmi;
-    requires transitive java.scripting;
     requires transitive java.xml;
     requires transitive org.apache.logging.log4j;
     requires transitive org.apache.logging.log4j.test;
diff --git a/log4j-core/src/main/java/module-info.java 
b/log4j-core/src/main/java/module-info.java
index d4b3d93..cb34b89 100644
--- a/log4j-core/src/main/java/module-info.java
+++ b/log4j-core/src/main/java/module-info.java
@@ -60,27 +60,28 @@ module org.apache.logging.log4j.core {
     exports org.apache.logging.log4j.core.util;
     exports org.apache.logging.log4j.core.util.datetime;
 
-    requires transitive java.desktop;
-    requires transitive java.management;
-    requires transitive java.naming;
-    requires transitive java.sql;
-    requires transitive java.rmi;
-    requires transitive java.scripting;
-    requires transitive java.xml;
+    // Required Dependenceis
     requires transitive org.apache.logging.log4j;
     requires transitive org.apache.logging.log4j.plugins;
-    requires transitive com.lmax.disruptor;
-    requires transitive org.jctools.core;
-    requires transitive org.osgi.framework;
-    requires transitive com.conversantmedia.disruptor;
-    requires transitive com.fasterxml.jackson.core;
-    requires transitive com.fasterxml.jackson.databind;
-    requires transitive com.fasterxml.jackson.dataformat.xml;
-    requires transitive com.fasterxml.jackson.dataformat.yaml;
-    requires transitive org.apache.commons.compress;
-    requires transitive org.fusesource.jansi;
+    // Optional Despendencies
+    requires static java.desktop;
+    requires static java.management;
+    requires static java.sql;
+    requires static java.rmi;
+    requires static java.xml;
+    requires static com.lmax.disruptor;
+    requires static org.jctools.core;
+    requires static org.osgi.framework;
+    requires static com.conversantmedia.disruptor;
+    requires static com.fasterxml.jackson.core;
+    requires static com.fasterxml.jackson.databind;
+    requires static com.fasterxml.jackson.dataformat.xml;
+    requires static com.fasterxml.jackson.dataformat.yaml;
+    requires static org.apache.commons.compress;
+    requires static org.fusesource.jansi;
     uses org.apache.logging.log4j.core.util.ContextDataProvider;
     uses org.apache.logging.log4j.core.util.WatchEventService;
+    uses org.apache.logging.log4j.core.script.ScriptManagerFactory;
     provides 
org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory with 
org.apache.logging.log4j.core.message.ExtendedThreadInfoFactory;
     provides org.apache.logging.log4j.core.util.ContextDataProvider with 
org.apache.logging.log4j.core.impl.ThreadContextDataProvider;
     provides org.apache.logging.log4j.spi.Provider with 
org.apache.logging.log4j.core.impl.Log4jProvider;
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/DeleteAction.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/DeleteAction.java
index c51c715..11ba5fb 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/DeleteAction.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/DeleteAction.java
@@ -26,6 +26,7 @@ import java.util.Objects;
 
 import org.apache.logging.log4j.core.Core;
 import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.script.ScriptConditional;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginAttribute;
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
@@ -41,7 +42,7 @@ public class DeleteAction extends AbstractPathAction {
 
     private final PathSorter pathSorter;
     private final boolean testMode;
-    private final ScriptCondition scriptCondition;
+    private final ScriptConditional scriptCondition;
 
     /**
      * Creates a new DeleteAction that starts scanning for files to delete 
from the specified base path.
@@ -60,7 +61,7 @@ public class DeleteAction extends AbstractPathAction {
      * @param scriptCondition
      */
     DeleteAction(final String basePath, final boolean followSymbolicLinks, 
final int maxDepth, final boolean testMode,
-            final PathSorter sorter, final PathCondition[] pathConditions, 
final ScriptCondition scriptCondition,
+            final PathSorter sorter, final PathCondition[] pathConditions, 
final ScriptConditional scriptCondition,
             final StrSubstitutor subst) {
         super(basePath, followSymbolicLinks, maxDepth, pathConditions, subst);
         this.testMode = testMode;
@@ -203,7 +204,7 @@ public class DeleteAction extends AbstractPathAction {
             @PluginAttribute final boolean testMode,
             @PluginElement final PathSorter sorterParameter,
             @PluginElement final PathCondition[] pathConditions,
-            @PluginElement final ScriptCondition scriptCondition,
+            @PluginElement final ScriptConditional scriptCondition,
             @PluginConfiguration final Configuration config) {
             // @formatter:on
         final PathSorter sorter = sorterParameter == null ? new 
PathSortByModificationTime(true) : sorterParameter;
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/Routes.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/Routes.java
index a7e0813..7355e2a 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/Routes.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/Routes.java
@@ -21,7 +21,8 @@ import org.apache.logging.log4j.core.Core;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
-import org.apache.logging.log4j.core.script.AbstractScript;
+import org.apache.logging.log4j.core.script.Script;
+import org.apache.logging.log4j.core.script.ScriptBindings;
 import org.apache.logging.log4j.core.script.ScriptManager;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginAttribute;
@@ -30,7 +31,6 @@ import org.apache.logging.log4j.plugins.PluginFactory;
 import org.apache.logging.log4j.plugins.validation.constraints.Required;
 import org.apache.logging.log4j.status.StatusLogger;
 
-import javax.script.Bindings;
 import java.util.Objects;
 import java.util.concurrent.ConcurrentMap;
 
@@ -53,7 +53,7 @@ public final class Routes {
         private String pattern;
 
         @PluginElement("Script")
-        private AbstractScript patternScript;
+        private Script patternScript;
 
         @PluginElement
         @Required
@@ -86,7 +86,7 @@ public final class Routes {
             return pattern;
         }
 
-        public AbstractScript getPatternScript() {
+        public Script getPatternScript() {
             return patternScript;
         }
 
@@ -104,7 +104,7 @@ public final class Routes {
             return this;
         }
 
-        public Builder setPatternScript(@SuppressWarnings("hiding") final 
AbstractScript patternScript) {
+        public Builder setPatternScript(@SuppressWarnings("hiding") final 
Script patternScript) {
             this.patternScript = patternScript;
             return this;
         }
@@ -127,12 +127,12 @@ public final class Routes {
 
     private final String pattern;
 
-    private final AbstractScript patternScript;
+    private final Script patternScript;
 
     // TODO Why not make this a Map or add a Map.
     private final Route[] routes;
 
-    private Routes(final Configuration configuration, final AbstractScript 
patternScript, final String pattern, final Route... routes) {
+    private Routes(final Configuration configuration, final Script 
patternScript, final String pattern, final Route... routes) {
         this.configuration = configuration;
         this.patternScript = patternScript;
         this.pattern = pattern;
@@ -148,7 +148,7 @@ public final class Routes {
     public String getPattern(final LogEvent event, final ConcurrentMap<Object, 
Object> scriptStaticVariables) {
         if (patternScript != null) {
             final ScriptManager scriptManager = 
configuration.getScriptManager();
-            final Bindings bindings = 
scriptManager.createBindings(patternScript);
+            final ScriptBindings bindings = 
scriptManager.createBindings(patternScript);
             bindings.put(STATIC_VARIABLES_KEY, scriptStaticVariables);
             bindings.put(LOG_EVENT_KEY, event);
             final Object object = 
scriptManager.execute(patternScript.getName(), bindings);
@@ -162,7 +162,7 @@ public final class Routes {
      * Gets the optional script that decides which route to pick.
      * @return the optional script that decides which route to pick. May be 
null.
      */
-    public AbstractScript getPatternScript() {
+    public Script getPatternScript() {
         return patternScript;
     }
 
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
index a1e9051..584eadd 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
@@ -25,14 +25,14 @@ import 
org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
 import org.apache.logging.log4j.core.config.AppenderControl;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.Property;
-import org.apache.logging.log4j.core.script.AbstractScript;
+import org.apache.logging.log4j.core.script.Script;
+import org.apache.logging.log4j.core.script.ScriptBindings;
 import org.apache.logging.log4j.core.script.ScriptManager;
 import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginElement;
 import org.apache.logging.log4j.plugins.PluginFactory;
 
-import javax.script.Bindings;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Objects;
@@ -59,7 +59,7 @@ public final class RoutingAppender extends AbstractAppender {
 
         // Does not work unless the element is called "Script", I wanted 
"DefaultRounteScript"...
         @PluginElement("Script")
-        private AbstractScript defaultRouteScript;
+        private Script defaultRouteScript;
 
         @PluginElement("Routes")
         private Routes routes;
@@ -92,7 +92,7 @@ public final class RoutingAppender extends AbstractAppender {
             return routes;
         }
 
-        public AbstractScript getDefaultRouteScript() {
+        public Script getDefaultRouteScript() {
             return defaultRouteScript;
         }
 
@@ -113,7 +113,7 @@ public final class RoutingAppender extends AbstractAppender 
{
             return asBuilder();
         }
 
-        public B setDefaultRouteScript(@SuppressWarnings("hiding") final 
AbstractScript defaultRouteScript) {
+        public B setDefaultRouteScript(@SuppressWarnings("hiding") final 
Script defaultRouteScript) {
             this.defaultRouteScript = defaultRouteScript;
             return asBuilder();
         }
@@ -151,13 +151,13 @@ public final class RoutingAppender extends 
AbstractAppender {
     private final ConcurrentMap<String, RouteAppenderControl> 
referencedAppenders = new ConcurrentHashMap<>();
     private final RewritePolicy rewritePolicy;
     private final PurgePolicy purgePolicy;
-    private final AbstractScript defaultRouteScript;
+    private final Script defaultRouteScript;
     private final ConcurrentMap<Object, Object> scriptStaticVariables = new 
ConcurrentHashMap<>();
     private final Boolean requiresLocation;
 
     private RoutingAppender(final String name, final Filter filter, final 
boolean ignoreExceptions, final Routes routes,
             final RewritePolicy rewritePolicy, final Configuration 
configuration, final PurgePolicy purgePolicy,
-            final AbstractScript defaultRouteScript, final Property[] 
properties, final Boolean requiresLocation) {
+            final Script defaultRouteScript, final Property[] properties, 
final Boolean requiresLocation) {
         super(name, filter, null, ignoreExceptions, properties);
         this.routes = routes;
         this.configuration = configuration;
@@ -189,7 +189,7 @@ public final class RoutingAppender extends AbstractAppender 
{
             } else {
                 final ScriptManager scriptManager = 
configuration.getScriptManager();
                 scriptManager.addScript(defaultRouteScript);
-                final Bindings bindings = 
scriptManager.createBindings(defaultRouteScript);
+                final ScriptBindings bindings = 
scriptManager.createBindings(defaultRouteScript);
                 bindings.put(STATIC_VARIABLES_KEY, scriptStaticVariables);
                 final Object object = 
scriptManager.execute(defaultRouteScript.getName(), bindings);
                 final Route route = routes.getRoute(Objects.toString(object, 
null));
@@ -365,7 +365,7 @@ public final class RoutingAppender extends AbstractAppender 
{
         return defaultRoute;
     }
 
-    public AbstractScript getDefaultRouteScript() {
+    public Script getDefaultRouteScript() {
         return defaultRouteScript;
     }
 
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index 8c1217a..1f00a2c 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -30,6 +30,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -59,9 +60,8 @@ import org.apache.logging.log4j.core.lookup.MapLookup;
 import org.apache.logging.log4j.core.lookup.StrLookup;
 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
 import org.apache.logging.log4j.core.net.Advertiser;
-import org.apache.logging.log4j.core.script.AbstractScript;
 import org.apache.logging.log4j.core.script.ScriptManager;
-import org.apache.logging.log4j.core.script.ScriptRef;
+import org.apache.logging.log4j.core.script.ScriptManagerFactory;
 import org.apache.logging.log4j.core.util.Constants;
 import org.apache.logging.log4j.core.time.internal.DummyNanoClock;
 import org.apache.logging.log4j.core.util.Loader;
@@ -75,6 +75,7 @@ import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.util.PluginManager;
 import org.apache.logging.log4j.plugins.util.PluginType;
 import org.apache.logging.log4j.util.PropertiesUtil;
+import org.apache.logging.log4j.util.ServiceLoaderUtil;
 
 /**
  * The base Configuration. Many configuration implementations will extend this 
class.
@@ -219,7 +220,10 @@ public abstract class AbstractConfiguration extends 
AbstractFilterable implement
         LOGGER.debug(Version.getProductString() + " initializing configuration 
{}", this);
         subst.setConfiguration(this);
         try {
-            scriptManager = new ScriptManager(this, watchManager);
+            ServiceLoaderUtil.loadServices(ScriptManagerFactory.class,
+                            (layer) -> ServiceLoader.load(layer, 
ScriptManagerFactory.class),
+                            
null).stream().findFirst().ifPresent(scriptManagerFactory ->
+                    scriptManager = 
scriptManagerFactory.createScriptManager(this, watchManager));
         } catch (final LinkageError | Exception e) {
             // LOG4J2-1920 ScriptEngineManager is not available in Android
             LOGGER.info("Cannot initialize scripting support because this JRE 
does not support it.", e);
@@ -641,14 +645,8 @@ public abstract class AbstractConfiguration extends 
AbstractFilterable implement
                 continue;
             }
             if (child.getName().equalsIgnoreCase("Scripts")) {
-                for (final AbstractScript script : 
child.getObject(AbstractScript[].class)) {
-                    if (script instanceof ScriptRef) {
-                        LOGGER.error("Script reference to {} not added. 
Scripts definition cannot contain script references",
-                                script.getName());
-                    } else {
-                        if (scriptManager != null) {
-                            scriptManager.addScript(script);
-                        }}
+                if (scriptManager != null) {
+                    scriptManager.addScripts(child);
                 }
             } else if (child.getName().equalsIgnoreCase("Appenders")) {
                 appenders = child.getObject();
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java
index dd98827..a59bb5f 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginBuilder.java
@@ -31,6 +31,7 @@ import 
org.apache.logging.log4j.plugins.inject.ConfigurationInjector;
 import org.apache.logging.log4j.plugins.util.Builder;
 import org.apache.logging.log4j.plugins.util.PluginType;
 import org.apache.logging.log4j.plugins.util.TypeUtil;
+import org.apache.logging.log4j.plugins.validation.PluginValidator;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.ReflectionUtil;
 import org.apache.logging.log4j.util.StringBuilders;
@@ -116,8 +117,14 @@ public class PluginBuilder implements Builder<Object> {
     @Override
     public Object build() {
         verify();
+        Class<?> pluginClass = pluginType.getPluginClass();
+        if (!PluginValidator.validatePlugin(pluginClass, 
pluginType.getElementName())) {
+            LOGGER.error("Could not create plugin builder for plugin {} due to 
constraint violations",
+                    pluginType.getElementName());
+            return null;
+        }
         LOGGER.debug("Building Plugin[name={}, class={}].", 
pluginType.getElementName(),
-                pluginType.getPluginClass().getName());
+                pluginClass.getName());
         substitutor = new Substitutor(event);
         // first try to use a builder class if one is available
         try {
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/Script.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/script/Script.java
index b51eb37..2e4fa13 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/Script.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/script/Script.java
@@ -16,47 +16,14 @@
  */
 package org.apache.logging.log4j.core.script;
 
-import org.apache.logging.log4j.plugins.Node;
-import org.apache.logging.log4j.plugins.Plugin;
-import org.apache.logging.log4j.plugins.PluginAttribute;
-import org.apache.logging.log4j.plugins.PluginFactory;
-import org.apache.logging.log4j.plugins.PluginValue;
-
 /**
- * Container for the language and body of a script.
+ * Represents int
  */
-@Plugin(name = Script.PLUGIN_NAME, category = Node.CATEGORY, printObject = 
true)
-public class Script extends AbstractScript {
-
-    private static final String ATTR_LANGUAGE = "language";
-    private static final String ATTR_SCRIPT_TEXT = "scriptText";
-    static final String PLUGIN_NAME = "Script";
-
-    public Script(final String name, final String language, final String 
scriptText) {
-        super(name, language, scriptText);
-    }
+public interface Script {
 
-    @PluginFactory
-    public static Script createScript(
-            // @formatter:off
-            @PluginAttribute final String name,
-            @PluginAttribute String language,
-            @PluginValue final String scriptText) {
-            // @formatter:on
-        if (language == null) {
-            LOGGER.error("No '{}' attribute provided for {} plugin '{}'", 
ATTR_LANGUAGE, PLUGIN_NAME, name);
-            language = DEFAULT_LANGUAGE;
-        }
-        if (scriptText == null) {
-            LOGGER.error("No '{}' attribute provided for {} plugin '{}'", 
ATTR_SCRIPT_TEXT, PLUGIN_NAME, name);
-            return null;
-        }
-        return new Script(name, language, scriptText);
+    String getLanguage();
 
-    }
+    String getScriptText();
 
-    @Override
-    public String toString() {
-        return getName() != null ? getName() : super.toString();
-    }
+    String getName();
 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptBindings.java
similarity index 86%
copy from 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
copy to 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptBindings.java
index 4964b30..181b03d 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptBindings.java
@@ -14,7 +14,14 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
+package org.apache.logging.log4j.core.script;
+
+import java.util.Map;
+
 /**
- * Log4j 2 Script support.
+ * Container for javax.script.Bindings.
  */
-package org.apache.logging.log4j.core.script;
+public interface ScriptBindings extends Map<String, Object> {
+
+
+}
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptConditional.java
similarity index 72%
copy from 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
copy to 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptConditional.java
index 4964b30..d00cddd 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptConditional.java
@@ -14,7 +14,16 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
+package org.apache.logging.log4j.core.script;
+
+import java.nio.file.Path;
+import java.util.List;
+
+import 
org.apache.logging.log4j.core.appender.rolling.action.PathWithAttributes;
+
 /**
- * Log4j 2 Script support.
+ * Interface for the ScriptCondition plugin.
  */
-package org.apache.logging.log4j.core.script;
+public interface ScriptConditional {
+    List<PathWithAttributes> selectFilesToDelete(final Path basePath, final 
List<PathWithAttributes> candidates);
+}
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptManager.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptManager.java
index 43c4f85..297426a 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptManager.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptManager.java
@@ -16,269 +16,23 @@
  */
 package org.apache.logging.log4j.core.script;
 
-import java.io.File;
-import java.io.Serializable;
-import java.nio.file.Path;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import javax.script.Bindings;
-import javax.script.Compilable;
-import javax.script.CompiledScript;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineFactory;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-import javax.script.SimpleBindings;
-
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.config.Configuration;
-import org.apache.logging.log4j.core.util.FileWatcher;
-import org.apache.logging.log4j.core.util.WatchManager;
-import org.apache.logging.log4j.status.StatusLogger;
-import org.apache.logging.log4j.util.Strings;
+import org.apache.logging.log4j.plugins.Node;
 
 /**
- * Manages the scripts use by the Configuration.
+ * Class Description goes here.
  */
-public class ScriptManager implements FileWatcher, Serializable {
-
-    private abstract class AbstractScriptRunner implements ScriptRunner {
-
-        private static final String KEY_STATUS_LOGGER = "statusLogger";
-        private static final String KEY_CONFIGURATION = "configuration";
-
-        @Override
-        public Bindings createBindings() {
-            final SimpleBindings bindings = new SimpleBindings();
-            bindings.put(KEY_CONFIGURATION, configuration);
-            bindings.put(KEY_STATUS_LOGGER, logger);
-            return bindings;
-        }
-
-    }
-
-    private static final long serialVersionUID = -2534169384971965196L;
-    private static final String KEY_THREADING = "THREADING";
-    private static final Logger logger = StatusLogger.getLogger();
-
-    private final Configuration configuration;
-    private final ScriptEngineManager manager = new ScriptEngineManager();
-    private final ConcurrentMap<String, ScriptRunner> scriptRunners = new 
ConcurrentHashMap<>();
-    private final String languages;
-    private final WatchManager watchManager;
-
-    public ScriptManager(final Configuration configuration, final WatchManager 
watchManager) {
-        this.configuration = configuration;
-        this.watchManager = watchManager;
-        final List<ScriptEngineFactory> factories = 
manager.getEngineFactories();
-        if (logger.isDebugEnabled()) {
-            final StringBuilder sb = new StringBuilder();
-            final int factorySize = factories.size();
-            logger.debug("Installed {} script engine{}", factorySize, 
factorySize != 1 ? "s" : Strings.EMPTY);
-            for (final ScriptEngineFactory factory : factories) {
-                String threading = 
Objects.toString(factory.getParameter(KEY_THREADING), null);
-                if (threading == null) {
-                    threading = "Not Thread Safe";
-                }
-                final StringBuilder names = new StringBuilder();
-                final List<String> languageNames = factory.getNames();
-                for (final String name : languageNames) {
-                    if (names.length() > 0) {
-                        names.append(", ");
-                    }
-                    names.append(name);
-                }
-                boolean compiled = false;
-                try {
-                    compiled = factory.getScriptEngine() instanceof Compilable;
-                    logger.debug("{} version: {}, language: {}, threading: {}, 
compile: {}, names: {}, factory class: {}",
-                            factory.getEngineName(), 
factory.getEngineVersion(), factory.getLanguageName(), threading,
-                            compiled, languageNames, 
factory.getClass().getName());
-                    if (sb.length() > 0) {
-                        sb.append(", ");
-                    }
-                    sb.append(names);
-                } catch (RuntimeException ex) {
-                    logger.warn("Error accessing scriptEngine for {}: {}", 
factory.getEngineName(), ex.getMessage());
-                }
-
-            }
-            languages = sb.toString();
-        } else {
-            final StringBuilder names = new StringBuilder();
-            for (final ScriptEngineFactory factory : factories) {
-                for (final String name : factory.getNames()) {
-                    if (names.length() > 0) {
-                        names.append(", ");
-                    }
-                    names.append(name);
-                }
-            }
-            languages = names.toString();
-        }
-    }
-
-    public void addScript(final AbstractScript script) {
-        final ScriptEngine engine = 
manager.getEngineByName(script.getLanguage());
-        if (engine == null) {
-            logger.error("No ScriptEngine found for language " + 
script.getLanguage() + ". Available languages are: "
-                    + languages);
-            return;
-        }
-        if (engine.getFactory().getParameter(KEY_THREADING) == null) {
-            scriptRunners.put(script.getName(), new 
ThreadLocalScriptRunner(script));
-        } else {
-            scriptRunners.put(script.getName(), new MainScriptRunner(engine, 
script));
-        }
-
-        if (script instanceof ScriptFile) {
-            final ScriptFile scriptFile = (ScriptFile) script;
-            final Path path = scriptFile.getPath();
-            if (scriptFile.isWatched() && path != null) {
-                watchManager.watchFile(path.toFile(), this);
-            }
-        }
-    }
-
-    public Bindings createBindings(final AbstractScript script) {
-        return getScriptRunner(script).createBindings();
-    }
-
-    public AbstractScript getScript(final String name) {
-        final ScriptRunner runner = scriptRunners.get(name);
-        return runner != null ? runner.getScript() : null;
-    }
-
-    @Override
-    public void fileModified(final File file) {
-        final ScriptRunner runner = scriptRunners.get(file.toString());
-        if (runner == null) {
-            logger.info("{} is not a running script", file.getName());
-            return;
-        }
-        final ScriptEngine engine = runner.getScriptEngine();
-        final AbstractScript script = runner.getScript();
-        if (engine.getFactory().getParameter(KEY_THREADING) == null) {
-            scriptRunners.put(script.getName(), new 
ThreadLocalScriptRunner(script));
-        } else {
-            scriptRunners.put(script.getName(), new MainScriptRunner(engine, 
script));
-        }
-
-    }
-
-    public Object execute(final String name, final Bindings bindings) {
-        final ScriptRunner scriptRunner = scriptRunners.get(name);
-        if (scriptRunner == null) {
-            logger.warn("No script named {} could be found", name);
-            return null;
-        }
-        return AccessController.doPrivileged((PrivilegedAction<Object>) () -> 
scriptRunner.execute(bindings));
-    }
-
-    private interface ScriptRunner {
-
-        Bindings createBindings();
-
-        Object execute(Bindings bindings);
-
-        AbstractScript getScript();
-
-        ScriptEngine getScriptEngine();
-    }
-
-    private class MainScriptRunner extends AbstractScriptRunner {
-        private final AbstractScript script;
-        private final CompiledScript compiledScript;
-        private final ScriptEngine scriptEngine;
-
-        public MainScriptRunner(final ScriptEngine scriptEngine, final 
AbstractScript script) {
-            this.script = script;
-            this.scriptEngine = scriptEngine;
-            CompiledScript compiled = null;
-            if (scriptEngine instanceof Compilable) {
-                logger.debug("Script {} is compilable", script.getName());
-                compiled = 
AccessController.doPrivileged((PrivilegedAction<CompiledScript>) () -> {
-                    try {
-                        return ((Compilable) 
scriptEngine).compile(script.getScriptText());
-                    } catch (final Throwable ex) {
-                        /*
-                         * ScriptException is what really should be caught 
here. However, beanshell's ScriptEngine
-                         * implements Compilable but then throws Error when 
the compile method is called!
-                         */
-                        logger.warn("Error compiling script", ex);
-                        return null;
-                    }
-                });
-            }
-            compiledScript = compiled;
-        }
-
-        @Override
-        public ScriptEngine getScriptEngine() {
-            return this.scriptEngine;
-        }
-
-        @Override
-        public Object execute(final Bindings bindings) {
-            if (compiledScript != null) {
-                try {
-                    return compiledScript.eval(bindings);
-                } catch (final ScriptException ex) {
-                    logger.error("Error running script " + script.getName(), 
ex);
-                    return null;
-                }
-            }
-            try {
-                return scriptEngine.eval(script.getScriptText(), bindings);
-            } catch (final ScriptException ex) {
-                logger.error("Error running script " + script.getName(), ex);
-                return null;
-            }
-        }
-
-        @Override
-        public AbstractScript getScript() {
-            return script;
-        }
-    }
-
-    private class ThreadLocalScriptRunner extends AbstractScriptRunner {
-        private final AbstractScript script;
-
-        private final ThreadLocal<MainScriptRunner> runners = new 
ThreadLocal<MainScriptRunner>() {
-            @Override
-            protected MainScriptRunner initialValue() {
-                final ScriptEngine engine = 
manager.getEngineByName(script.getLanguage());
-                return new MainScriptRunner(engine, script);
-            }
-        };
-
-        public ThreadLocalScriptRunner(final AbstractScript script) {
-            this.script = script;
-        }
+public interface ScriptManager {
 
-        @Override
-        public Object execute(final Bindings bindings) {
-            return runners.get().execute(bindings);
-        }
+    /**
+     * Add scripts defined in the configuration.
+     * @param child The Scripts node.
+     */
+    void addScripts(Node child);
+    void addScript(final Script script);
 
-        @Override
-        public AbstractScript getScript() {
-            return script;
-        }
+    ScriptBindings createBindings(final Script script);
 
-        @Override
-        public ScriptEngine getScriptEngine() {
-            return runners.get().getScriptEngine();
-        }
-    }
+    Script getScript(final String name);
 
-    private ScriptRunner getScriptRunner(final AbstractScript script) {
-        return scriptRunners.get(script.getName());
-    }
+    Object execute(final String name, final ScriptBindings bindings);
 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptManagerFactory.java
similarity index 74%
copy from 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
copy to 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptManagerFactory.java
index 4964b30..d4711d3 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptManagerFactory.java
@@ -14,7 +14,15 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
+package org.apache.logging.log4j.core.script;
+
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.util.WatchManager;
+
 /**
- * Log4j 2 Script support.
+ * Interface to create a ScriptManager.
  */
-package org.apache.logging.log4j.core.script;
+public interface ScriptManagerFactory {
+
+    ScriptManager createScriptManager(Configuration configuration, 
WatchManager watchManager);
+}
diff --git a/log4j-jpl/pom.xml b/log4j-jpl/pom.xml
index 7c0cd91..b940b7d 100644
--- a/log4j-jpl/pom.xml
+++ b/log4j-jpl/pom.xml
@@ -43,7 +43,12 @@
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-core</artifactId>
-      <scope>test</scope>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>com.lmax</groupId>
+      <artifactId>disruptor</artifactId>
+      <optional>true</optional>
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
diff --git a/log4j-jpl/src/main/java/module-info.java 
b/log4j-jpl/src/main/java/module-info.java
index 2788318..0b5affa 100644
--- a/log4j-jpl/src/main/java/module-info.java
+++ b/log4j-jpl/src/main/java/module-info.java
@@ -16,6 +16,7 @@
  */
 module org.apache.logging.log4j.jpl {
     requires org.apache.logging.log4j;
+    requires transitive org.apache.logging.log4j.core;
 
     provides java.lang.System.LoggerFinder with 
org.apache.logging.log4j.jpl.Log4jSystemLoggerFinder;
 }
diff --git a/log4j-plugins/src/main/java/module-info.java 
b/log4j-plugins/src/main/java/module-info.java
index 20f1f17..d6150e1 100644
--- a/log4j-plugins/src/main/java/module-info.java
+++ b/log4j-plugins/src/main/java/module-info.java
@@ -29,8 +29,9 @@ module org.apache.logging.log4j.plugins {
     exports org.apache.logging.log4j.plugins.name;
 
     requires org.apache.logging.log4j;
-    requires transitive org.osgi.framework;
+    requires static org.osgi.framework;
 
     uses org.apache.logging.log4j.plugins.processor.PluginService;
     provides org.apache.logging.log4j.plugins.processor.PluginService with 
org.apache.logging.log4j.plugins.convert.plugins.Log4jPlugins;
+
 }
diff --git 
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
index f0fef7c..7019d54 100644
--- 
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
+++ 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
@@ -195,13 +195,23 @@ public class PluginRegistry {
      * @since 3.0
      */
     public void loadPlugins(Map<String, List<PluginType<?>>> map) {
+        Throwable throwable = null;
+        ClassLoader errorClassLoader = null;
+        boolean allFail = true;
         for (ClassLoader classLoader : LoaderUtil.getClassLoaders()) {
             try {
                 loadPlugins(classLoader, map);
+                allFail = false;
             } catch (Throwable ex) {
-                LOGGER.debug("Unable to retrieve provider from ClassLoader 
{}", classLoader, ex);
+                if (throwable == null) {
+                    throwable = ex;
+                    errorClassLoader = classLoader;
+                }
             }
         }
+        if (allFail && throwable != null) {
+            LOGGER.debug("Unable to retrieve provider from ClassLoader {}", 
errorClassLoader, throwable);
+        }
     }
 
     /**
diff --git 
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
index 3e1a4b1..b379506 100644
--- 
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
+++ 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
@@ -17,7 +17,11 @@
 package org.apache.logging.log4j.plugins.util;
 
 
+import java.util.Collection;
+
 import org.apache.logging.log4j.plugins.processor.PluginEntry;
+import org.apache.logging.log4j.plugins.validation.ConstraintValidator;
+import org.apache.logging.log4j.plugins.validation.ConstraintValidators;
 
 /**
  * Plugin Descriptor. This is a memento object for Plugin annotations paired 
to their annotated classes.
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/PluginValidator.java
similarity index 56%
copy from 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
copy to 
log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/PluginValidator.java
index 4964b30..3727c0e 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
+++ 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/PluginValidator.java
@@ -14,7 +14,24 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
+package org.apache.logging.log4j.plugins.validation;
+
+import java.util.Collection;
+
 /**
- * Log4j 2 Script support.
+ * Performs validation on the Plugin to determine if it can be used.
  */
-package org.apache.logging.log4j.core.script;
+public class PluginValidator {
+
+
+    public static boolean validatePlugin(Class<?> pluginClass, String 
elementName) {
+        Collection<ConstraintValidator<?>> validators =
+                
ConstraintValidators.findValidators(pluginClass.getAnnotations());
+        for (ConstraintValidator<?> validator : validators) {
+            if (!validator.isValid(elementName, pluginClass)) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git 
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/constraints/RequiredClass.java
 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/constraints/RequiredClass.java
new file mode 100644
index 0000000..d640e39
--- /dev/null
+++ 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/constraints/RequiredClass.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.plugins.validation.constraints;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.logging.log4j.plugins.validation.Constraint;
+import 
org.apache.logging.log4j.plugins.validation.validators.RequiredClassValidator;
+
+/**
+ * Marks a plugin builder field or plugin factory parameter as required.
+ *
+ * @since 3.0.0
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@Constraint(RequiredClassValidator.class)
+public @interface RequiredClass {
+
+    /** The fully qualified name of the Class that is required */
+    String value();
+
+    /**
+     * The message to be logged if this constraint is violated. This should 
normally be overridden.
+     * @return the message to be logged if the constraint is violated.
+     */
+    String message() default "The required class is not present";
+}
+
diff --git 
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/constraints/RequiredProperty.java
 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/constraints/RequiredProperty.java
new file mode 100644
index 0000000..9c5d884
--- /dev/null
+++ 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/constraints/RequiredProperty.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.plugins.validation.constraints;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.logging.log4j.plugins.validation.Constraint;
+import 
org.apache.logging.log4j.plugins.validation.validators.RequiredPropertyValidator;
+
+/**
+ * Marks a plugin as requiring a property to be set, possibly to a specific 
value.
+ *
+ * @since 3.0.0
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@Constraint(RequiredPropertyValidator.class)
+public @interface RequiredProperty {
+
+    /** The name of the property that is required */
+    String name();
+    /** The value that the property is required to be set to. */
+    String value() default "";
+
+    /**
+     * The message to be logged if this constraint is violated. This should 
normally be overridden.
+     * @return the message to be logged if the constraint is violated.
+     */
+    String message() default "The required property is not present or has an 
incorrect value";
+}
+
diff --git 
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/validators/RequiredClassValidator.java
 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/validators/RequiredClassValidator.java
new file mode 100644
index 0000000..05622f6
--- /dev/null
+++ 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/validators/RequiredClassValidator.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.plugins.validation.validators;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.plugins.validation.ConstraintValidator;
+import org.apache.logging.log4j.plugins.validation.constraints.Required;
+import org.apache.logging.log4j.plugins.validation.constraints.RequiredClass;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.util.Assert;
+import org.apache.logging.log4j.util.LoaderUtil;
+
+/**
+ * Validator that checks for the existence of a class that is required.
+ * <ul>
+ * <li>The value {@code null}</li>
+ * <li>An object of type {@link CharSequence} with length 0</li>
+ * <li>An empty array</li>
+ * <li>An empty {@link Collection}</li>
+ * <li>An empty {@link Map}</li>
+ * </ul>
+ *
+ * @since 2.1
+ */
+public class RequiredClassValidator implements 
ConstraintValidator<RequiredClass> {
+
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    private RequiredClass annotation;
+
+    @Override
+    public void initialize(final RequiredClass anAnnotation) {
+        this.annotation = anAnnotation;
+    }
+
+    @Override
+    public boolean isValid(final String name, final Object value) {
+        boolean isValid = LoaderUtil.isClassAvailable(annotation.value());
+        if (!isValid) {
+            LOGGER.error("{} cannot be used. {} is unavailable.", name, 
annotation.value());
+        }
+        return isValid;
+    }
+}
diff --git 
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/validators/RequiredPropertyValidator.java
 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/validators/RequiredPropertyValidator.java
new file mode 100644
index 0000000..f17bd0e
--- /dev/null
+++ 
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/validators/RequiredPropertyValidator.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.plugins.validation.validators;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.plugins.validation.ConstraintValidator;
+import 
org.apache.logging.log4j.plugins.validation.constraints.RequiredProperty;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.util.PropertiesUtil;
+
+/**
+ * Validator that checks that a property exists and has the correct value if a 
value is required.
+ * <ul>
+ * <li>The value {@code null}</li>
+ * <li>An object of type {@link CharSequence} with length 0</li>
+ * <li>An empty array</li>
+ * <li>An empty {@link Collection}</li>
+ * <li>An empty {@link Map}</li>
+ * </ul>
+ *
+ * @since 3.0.0
+ */
+public class RequiredPropertyValidator implements 
ConstraintValidator<RequiredProperty> {
+
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    private RequiredProperty annotation;
+
+    @Override
+    public void initialize(final RequiredProperty anAnnotation) {
+        this.annotation = anAnnotation;
+    }
+
+    @Override
+    public boolean isValid(final String name, final Object value) {
+        String property = 
PropertiesUtil.getProperties().getStringProperty(annotation.name());
+        if (property == null) {
+            LOGGER.error("{} cannot be used. Required property {} is not 
defined", name, annotation.name());
+            return false;
+        }
+        if (annotation.value().length() > 0 && 
!annotation.value().equalsIgnoreCase(property)) {
+            LOGGER.error("{} cannot be used. Required property {} is not set 
to {}", name, annotation.name(),
+                    annotation.value());
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/log4j-script/pom.xml b/log4j-script/pom.xml
index 816b0e4..de51e43 100644
--- a/log4j-script/pom.xml
+++ b/log4j-script/pom.xml
@@ -62,6 +62,33 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.openjdk.nashorn</groupId>
+      <artifactId>nashorn-core</artifactId>
+      <version>15.3</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.groovy</groupId>
+      <artifactId>groovy</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.groovy</groupId>
+      <artifactId>groovy-jsr223</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.groovy</groupId>
+      <artifactId>groovy-dateutil</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache-extras.beanshell</groupId>
+      <artifactId>bsh</artifactId>
+      <scope>test</scope>
     </dependency>
   </dependencies>
 
diff --git a/log4j-script/src/main/java/module-info.java 
b/log4j-script/src/main/java/module-info.java
new file mode 100644
index 0000000..7f4d466
--- /dev/null
+++ b/log4j-script/src/main/java/module-info.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+module org.apache.logging.log4j.script {
+
+    exports org.apache.logging.log4j.script;
+    exports org.apache.logging.log4j.script.appender;
+    exports org.apache.logging.log4j.script.appender.rolling.action;
+    exports org.apache.logging.log4j.script.config.arbiter;
+    exports org.apache.logging.log4j.script.filter;
+    exports org.apache.logging.log4j.script.layout;
+
+    opens org.apache.logging.log4j.script.appender;
+    opens org.apache.logging.log4j.script.config.arbiter to 
org.apache.logging.log4j.core;
+    opens org.apache.logging.log4j.script.layout to 
org.apache.logging.log4j.core;
+
+    requires java.scripting;
+    requires org.apache.logging.log4j;
+    requires org.apache.logging.log4j.plugins;
+    requires org.apache.logging.log4j.core;
+    provides org.apache.logging.log4j.plugins.processor.PluginService with 
org.apache.logging.log4j.script.plugins.Log4jPlugins;
+    provides org.apache.logging.log4j.core.script.ScriptManagerFactory with 
org.apache.logging.log4j.script.factory.ScriptManagerFactoryImpl;
+}
\ No newline at end of file
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/AbstractScript.java
 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/AbstractScript.java
similarity index 92%
rename from 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/AbstractScript.java
rename to 
log4j-script/src/main/java/org/apache/logging/log4j/script/AbstractScript.java
index b78bff2..ff645cd 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/AbstractScript.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/AbstractScript.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.script;
+package org.apache.logging.log4j.script;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.status.StatusLogger;
@@ -22,7 +22,7 @@ import org.apache.logging.log4j.status.StatusLogger;
 /**
  * Container for the language and body of a script.
  */
-public abstract class AbstractScript {
+public abstract class AbstractScript implements 
org.apache.logging.log4j.core.script.Script {
 
     protected static final Logger LOGGER = StatusLogger.getLogger();
     protected static final String DEFAULT_LANGUAGE = "JavaScript";
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptFile.java 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptFile.java
similarity index 99%
rename from 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptFile.java
rename to 
log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptFile.java
index 6d52051..adc701e 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptFile.java
+++ b/log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptFile.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.script;
+package org.apache.logging.log4j.script;
 
 import java.io.File;
 import java.io.FileInputStream;
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptManager.java
 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptManagerImpl.java
similarity index 82%
copy from 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptManager.java
copy to 
log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptManagerImpl.java
index 43c4f85..46a7b2d 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptManager.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptManagerImpl.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.script;
+package org.apache.logging.log4j.script;
 
 import java.io.File;
 import java.io.Serializable;
@@ -37,15 +37,19 @@ import javax.script.SimpleBindings;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.script.Script;
+import org.apache.logging.log4j.core.script.ScriptBindings;
+import org.apache.logging.log4j.core.script.ScriptManager;
 import org.apache.logging.log4j.core.util.FileWatcher;
 import org.apache.logging.log4j.core.util.WatchManager;
+import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.Strings;
 
 /**
  * Manages the scripts use by the Configuration.
  */
-public class ScriptManager implements FileWatcher, Serializable {
+public class ScriptManagerImpl implements ScriptManager, FileWatcher, 
Serializable {
 
     private abstract class AbstractScriptRunner implements ScriptRunner {
 
@@ -53,8 +57,8 @@ public class ScriptManager implements FileWatcher, 
Serializable {
         private static final String KEY_CONFIGURATION = "configuration";
 
         @Override
-        public Bindings createBindings() {
-            final SimpleBindings bindings = new SimpleBindings();
+        public ScriptBindings createBindings() {
+            final ScriptBindings bindings = new ScriptBindingsImpl();
             bindings.put(KEY_CONFIGURATION, configuration);
             bindings.put(KEY_STATUS_LOGGER, logger);
             return bindings;
@@ -62,6 +66,9 @@ public class ScriptManager implements FileWatcher, 
Serializable {
 
     }
 
+    private static class ScriptBindingsImpl extends SimpleBindings implements 
ScriptBindings {
+    }
+
     private static final long serialVersionUID = -2534169384971965196L;
     private static final String KEY_THREADING = "THREADING";
     private static final Logger logger = StatusLogger.getLogger();
@@ -72,7 +79,7 @@ public class ScriptManager implements FileWatcher, 
Serializable {
     private final String languages;
     private final WatchManager watchManager;
 
-    public ScriptManager(final Configuration configuration, final WatchManager 
watchManager) {
+    public ScriptManagerImpl(final Configuration configuration, final 
WatchManager watchManager) {
         this.configuration = configuration;
         this.watchManager = watchManager;
         final List<ScriptEngineFactory> factories = 
manager.getEngineFactories();
@@ -123,7 +130,18 @@ public class ScriptManager implements FileWatcher, 
Serializable {
         }
     }
 
-    public void addScript(final AbstractScript script) {
+    public void addScripts(Node child) {
+        for (final AbstractScript script : 
child.getObject(AbstractScript[].class)) {
+            if (script instanceof ScriptRef) {
+                logger.error("Script reference to {} not added. Scripts 
definition cannot contain script references",
+                        script.getName());
+            } else {
+                addScript(script);
+            }
+        }
+    }
+
+    public void addScript(final Script script) {
         final ScriptEngine engine = 
manager.getEngineByName(script.getLanguage());
         if (engine == null) {
             logger.error("No ScriptEngine found for language " + 
script.getLanguage() + ". Available languages are: "
@@ -145,11 +163,15 @@ public class ScriptManager implements FileWatcher, 
Serializable {
         }
     }
 
-    public Bindings createBindings(final AbstractScript script) {
+    public static ScriptBindings createBindings() {
+        return new ScriptBindingsImpl();
+    }
+
+    public ScriptBindings createBindings(final Script script) {
         return getScriptRunner(script).createBindings();
     }
 
-    public AbstractScript getScript(final String name) {
+    public Script getScript(final String name) {
         final ScriptRunner runner = scriptRunners.get(name);
         return runner != null ? runner.getScript() : null;
     }
@@ -162,7 +184,7 @@ public class ScriptManager implements FileWatcher, 
Serializable {
             return;
         }
         final ScriptEngine engine = runner.getScriptEngine();
-        final AbstractScript script = runner.getScript();
+        final Script script = runner.getScript();
         if (engine.getFactory().getParameter(KEY_THREADING) == null) {
             scriptRunners.put(script.getName(), new 
ThreadLocalScriptRunner(script));
         } else {
@@ -171,7 +193,7 @@ public class ScriptManager implements FileWatcher, 
Serializable {
 
     }
 
-    public Object execute(final String name, final Bindings bindings) {
+    public Object execute(final String name, final ScriptBindings bindings) {
         final ScriptRunner scriptRunner = scriptRunners.get(name);
         if (scriptRunner == null) {
             logger.warn("No script named {} could be found", name);
@@ -182,21 +204,21 @@ public class ScriptManager implements FileWatcher, 
Serializable {
 
     private interface ScriptRunner {
 
-        Bindings createBindings();
+        ScriptBindings createBindings();
 
-        Object execute(Bindings bindings);
+        Object execute(ScriptBindings bindings);
 
-        AbstractScript getScript();
+        Script getScript();
 
         ScriptEngine getScriptEngine();
     }
 
     private class MainScriptRunner extends AbstractScriptRunner {
-        private final AbstractScript script;
+        private final Script script;
         private final CompiledScript compiledScript;
         private final ScriptEngine scriptEngine;
 
-        public MainScriptRunner(final ScriptEngine scriptEngine, final 
AbstractScript script) {
+        public MainScriptRunner(final ScriptEngine scriptEngine, final Script 
script) {
             this.script = script;
             this.scriptEngine = scriptEngine;
             CompiledScript compiled = null;
@@ -224,17 +246,17 @@ public class ScriptManager implements FileWatcher, 
Serializable {
         }
 
         @Override
-        public Object execute(final Bindings bindings) {
+        public Object execute(final ScriptBindings bindings) {
             if (compiledScript != null) {
                 try {
-                    return compiledScript.eval(bindings);
+                    return compiledScript.eval((Bindings) bindings);
                 } catch (final ScriptException ex) {
                     logger.error("Error running script " + script.getName(), 
ex);
                     return null;
                 }
             }
             try {
-                return scriptEngine.eval(script.getScriptText(), bindings);
+                return scriptEngine.eval(script.getScriptText(), (Bindings) 
bindings);
             } catch (final ScriptException ex) {
                 logger.error("Error running script " + script.getName(), ex);
                 return null;
@@ -242,13 +264,13 @@ public class ScriptManager implements FileWatcher, 
Serializable {
         }
 
         @Override
-        public AbstractScript getScript() {
+        public Script getScript() {
             return script;
         }
     }
 
     private class ThreadLocalScriptRunner extends AbstractScriptRunner {
-        private final AbstractScript script;
+        private final Script script;
 
         private final ThreadLocal<MainScriptRunner> runners = new 
ThreadLocal<MainScriptRunner>() {
             @Override
@@ -258,17 +280,17 @@ public class ScriptManager implements FileWatcher, 
Serializable {
             }
         };
 
-        public ThreadLocalScriptRunner(final AbstractScript script) {
+        public ThreadLocalScriptRunner(final Script script) {
             this.script = script;
         }
 
         @Override
-        public Object execute(final Bindings bindings) {
+        public Object execute(final ScriptBindings bindings) {
             return runners.get().execute(bindings);
         }
 
         @Override
-        public AbstractScript getScript() {
+        public Script getScript() {
             return script;
         }
 
@@ -278,7 +300,7 @@ public class ScriptManager implements FileWatcher, 
Serializable {
         }
     }
 
-    private ScriptRunner getScriptRunner(final AbstractScript script) {
+    private ScriptRunner getScriptRunner(final Script script) {
         return scriptRunners.get(script.getName());
     }
 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/Script.java 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptPlugin.java
similarity index 84%
copy from 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/Script.java
copy to 
log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptPlugin.java
index b51eb37..1e1c3c8 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/Script.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptPlugin.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.script;
+package org.apache.logging.log4j.script;
 
 import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.Plugin;
@@ -25,19 +25,19 @@ import org.apache.logging.log4j.plugins.PluginValue;
 /**
  * Container for the language and body of a script.
  */
-@Plugin(name = Script.PLUGIN_NAME, category = Node.CATEGORY, printObject = 
true)
-public class Script extends AbstractScript {
+@Plugin(name = ScriptPlugin.PLUGIN_NAME, category = Node.CATEGORY, printObject 
= true)
+public class ScriptPlugin extends AbstractScript {
 
     private static final String ATTR_LANGUAGE = "language";
     private static final String ATTR_SCRIPT_TEXT = "scriptText";
     static final String PLUGIN_NAME = "Script";
 
-    public Script(final String name, final String language, final String 
scriptText) {
+    public ScriptPlugin(final String name, final String language, final String 
scriptText) {
         super(name, language, scriptText);
     }
 
     @PluginFactory
-    public static Script createScript(
+    public static ScriptPlugin createScript(
             // @formatter:off
             @PluginAttribute final String name,
             @PluginAttribute String language,
@@ -51,7 +51,7 @@ public class Script extends AbstractScript {
             LOGGER.error("No '{}' attribute provided for {} plugin '{}'", 
ATTR_SCRIPT_TEXT, PLUGIN_NAME, name);
             return null;
         }
-        return new Script(name, language, scriptText);
+        return new ScriptPlugin(name, language, scriptText);
 
     }
 
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptRef.java 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptRef.java
similarity index 88%
rename from 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptRef.java
rename to 
log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptRef.java
index abec150..d165ff4 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/ScriptRef.java
+++ b/log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptRef.java
@@ -14,9 +14,11 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.script;
+package org.apache.logging.log4j.script;
 
 import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.script.Script;
+import org.apache.logging.log4j.core.script.ScriptManager;
 import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginAttribute;
@@ -38,14 +40,14 @@ public class ScriptRef extends AbstractScript {
 
     @Override
     public String getLanguage() {
-        final AbstractScript script = this.scriptManager.getScript(getName());
+        final Script script = this.scriptManager.getScript(getName());
         return script != null ? script.getLanguage() : null;
     }
 
 
     @Override
     public String getScriptText() {
-        final AbstractScript script = this.scriptManager.getScript(getName());
+        final Script script = this.scriptManager.getScript(getName());
         return script != null ? script.getScriptText() : null;
     }
 
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ScriptsPlugin.java
 b/log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptsPlugin.java
similarity index 93%
rename from 
log4j-core/src/main/java/org/apache/logging/log4j/core/config/ScriptsPlugin.java
rename to 
log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptsPlugin.java
index 6329f89..d4e2f92 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ScriptsPlugin.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/ScriptsPlugin.java
@@ -14,13 +14,12 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.config;
+package org.apache.logging.log4j.script;
 
 import org.apache.logging.log4j.core.Core;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginElement;
 import org.apache.logging.log4j.plugins.PluginFactory;
-import org.apache.logging.log4j.core.script.AbstractScript;
 
 /**
  * A  container of Scripts.
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ScriptAppenderSelector.java
 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/appender/ScriptAppenderSelector.java
similarity index 79%
rename from 
log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ScriptAppenderSelector.java
rename to 
log4j-script/src/main/java/org/apache/logging/log4j/script/appender/ScriptAppenderSelector.java
index cfcf580..0ea9fb2 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ScriptAppenderSelector.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/appender/ScriptAppenderSelector.java
@@ -14,25 +14,28 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.appender;
+package org.apache.logging.log4j.script.appender;
 
+import org.apache.logging.log4j.core.AbstractLifeCycle;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Core;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.appender.AppenderSet;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.Property;
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
-import org.apache.logging.log4j.core.script.AbstractScript;
+import org.apache.logging.log4j.core.script.ScriptBindings;
 import org.apache.logging.log4j.core.script.ScriptManager;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginBuilderAttribute;
 import org.apache.logging.log4j.plugins.PluginElement;
 import org.apache.logging.log4j.plugins.PluginFactory;
 import org.apache.logging.log4j.plugins.validation.constraints.Required;
+import org.apache.logging.log4j.script.AbstractScript;
 
-import javax.script.Bindings;
 import java.io.Serializable;
 import java.util.Objects;
 
@@ -63,29 +66,32 @@ public class ScriptAppenderSelector extends 
AbstractAppender {
         @Override
         public Appender build() {
             if (name == null) {
-                LOGGER.error("Name missing.");
+                AbstractLifeCycle.LOGGER.error("Name missing.");
                 return null;
             }
             if (script == null) {
-                LOGGER.error("Script missing for ScriptAppenderSelector 
appender {}", name);
+                AbstractLifeCycle.LOGGER.error("Script missing for 
ScriptAppenderSelector appender {}", name);
                 return null;
             }
             if (appenderSet == null) {
-                LOGGER.error("AppenderSet missing for ScriptAppenderSelector 
appender {}", name);
+                AbstractLifeCycle.LOGGER.error("AppenderSet missing for 
ScriptAppenderSelector appender {}", name);
                 return null;
             }
             if (configuration == null) {
-                LOGGER.error("Configuration missing for ScriptAppenderSelector 
appender {}", name);
+                AbstractLifeCycle.LOGGER.error("Configuration missing for 
ScriptAppenderSelector appender {}", name);
                 return null;
             }
             final ScriptManager scriptManager = 
configuration.getScriptManager();
+            if (scriptManager == null) {
+                return null;
+            }
             scriptManager.addScript(script);
-            final Bindings bindings = scriptManager.createBindings(script);
-            LOGGER.debug("ScriptAppenderSelector '{}' executing {} '{}': {}", 
name, script.getLanguage(),
+            final ScriptBindings bindings = 
scriptManager.createBindings(script);
+            AbstractLifeCycle.LOGGER.debug("ScriptAppenderSelector '{}' 
executing {} '{}': {}", name, script.getLanguage(),
                     script.getName(), script.getScriptText());
             final Object object = scriptManager.execute(script.getName(), 
bindings);
             final String actualAppenderName = Objects.toString(object, null);
-            LOGGER.debug("ScriptAppenderSelector '{}' selected '{}'", name, 
actualAppenderName);
+            AbstractLifeCycle.LOGGER.debug("ScriptAppenderSelector '{}' 
selected '{}'", name, actualAppenderName);
             return appenderSet.createAppender(actualAppenderName, name);
         }
 
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptCondition.java
 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/appender/rolling/action/ScriptCondition.java
similarity index 87%
rename from 
log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptCondition.java
rename to 
log4j-script/src/main/java/org/apache/logging/log4j/script/appender/rolling/action/ScriptCondition.java
index 2f6a0f6..744d5bb 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptCondition.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/appender/rolling/action/ScriptCondition.java
@@ -15,7 +15,7 @@
  * limitations under the license.
  */
 
-package org.apache.logging.log4j.core.appender.rolling.action;
+package org.apache.logging.log4j.script.appender.rolling.action;
 
 import java.nio.file.Path;
 import java.util.List;
@@ -25,14 +25,17 @@ import javax.script.SimpleBindings;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.Core;
+import 
org.apache.logging.log4j.core.appender.rolling.action.PathWithAttributes;
 import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.script.Script;
+import org.apache.logging.log4j.core.script.ScriptBindings;
+import org.apache.logging.log4j.core.script.ScriptConditional;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
 import org.apache.logging.log4j.plugins.PluginElement;
 import org.apache.logging.log4j.plugins.PluginFactory;
-import org.apache.logging.log4j.core.script.AbstractScript;
-import org.apache.logging.log4j.core.script.ScriptFile;
-import org.apache.logging.log4j.core.script.ScriptRef;
+import org.apache.logging.log4j.script.ScriptManagerImpl;
+import org.apache.logging.log4j.script.ScriptRef;
 import org.apache.logging.log4j.status.StatusLogger;
 
 /**
@@ -42,10 +45,10 @@ import org.apache.logging.log4j.status.StatusLogger;
  * @see #createCondition(AbstractScript, Configuration)
  */
 @Plugin(name = "ScriptCondition", category = Core.CATEGORY_NAME, printObject = 
true)
-public class ScriptCondition {
+public class ScriptCondition implements ScriptConditional {
     private static final Logger LOGGER = StatusLogger.getLogger();
 
-    private final AbstractScript script;
+    private final Script script;
     private final Configuration configuration;
 
     /**
@@ -54,7 +57,7 @@ public class ScriptCondition {
      * @param script the script that can select files to delete
      * @param configuration configuration containing the StrSubstitutor passed 
to the script
      */
-    public ScriptCondition(final AbstractScript script, final Configuration 
configuration) {
+    public ScriptCondition(final Script script, final Configuration 
configuration) {
         this.script = Objects.requireNonNull(script, "script");
         this.configuration = Objects.requireNonNull(configuration, 
"configuration");
         if (!(script instanceof ScriptRef)) {
@@ -71,7 +74,7 @@ public class ScriptCondition {
      */
     @SuppressWarnings("unchecked")
     public List<PathWithAttributes> selectFilesToDelete(final Path basePath, 
final List<PathWithAttributes> candidates) {
-        final SimpleBindings bindings = new SimpleBindings();
+        final ScriptBindings bindings = ScriptManagerImpl.createBindings();
         bindings.put("basePath", basePath);
         bindings.put("pathList", candidates);
         bindings.putAll(configuration.getProperties());
@@ -102,7 +105,7 @@ public class ScriptCondition {
      * @return A ScriptCondition.
      */
     @PluginFactory
-    public static ScriptCondition createCondition(@PluginElement("Script") 
final AbstractScript script,
+    public static ScriptCondition createCondition(@PluginElement("Script") 
final Script script,
             @PluginConfiguration final Configuration configuration) {
 
         if (script == null) {
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/arbiters/ScriptArbiter.java
 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/config/arbiter/ScriptArbiter.java
similarity index 86%
rename from 
log4j-core/src/main/java/org/apache/logging/log4j/core/config/arbiters/ScriptArbiter.java
rename to 
log4j-script/src/main/java/org/apache/logging/log4j/script/config/arbiter/ScriptArbiter.java
index c968a32..35d06ec 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/arbiters/ScriptArbiter.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/config/arbiter/ScriptArbiter.java
@@ -14,21 +14,22 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.config.arbiters;
-
-import javax.script.SimpleBindings;
+package org.apache.logging.log4j.script.config.arbiter;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.config.AbstractConfiguration;
 import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.arbiters.Arbiter;
 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
 import org.apache.logging.log4j.core.config.plugins.PluginNode;
-import org.apache.logging.log4j.core.script.AbstractScript;
-import org.apache.logging.log4j.core.script.ScriptRef;
+import org.apache.logging.log4j.core.script.Script;
+import org.apache.logging.log4j.core.script.ScriptBindings;
 import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.util.PluginType;
+import org.apache.logging.log4j.script.ScriptManagerImpl;
+import org.apache.logging.log4j.script.ScriptRef;
 import org.apache.logging.log4j.status.StatusLogger;
 
 /**
@@ -38,10 +39,10 @@ import org.apache.logging.log4j.status.StatusLogger;
         deferChildren = true, printObject = true)
 public class ScriptArbiter implements Arbiter {
 
-    private final AbstractScript script;
+    private final Script script;
     private final Configuration configuration;
 
-    private ScriptArbiter(final Configuration configuration, final 
AbstractScript script) {
+    private ScriptArbiter(final Configuration configuration, final Script 
script) {
         this.configuration = configuration;
         this.script = script;
         if (!(script instanceof ScriptRef)) {
@@ -54,7 +55,7 @@ public class ScriptArbiter implements Arbiter {
      */
     @Override
     public boolean isCondition() {
-        final SimpleBindings bindings = new SimpleBindings();
+        final ScriptBindings bindings = ScriptManagerImpl.createBindings();
         bindings.putAll(configuration.getProperties());
         bindings.put("substitutor", configuration.getStrSubstitutor());
         final Object object = 
configuration.getScriptManager().execute(script.getName(), bindings);
@@ -91,15 +92,15 @@ public class ScriptArbiter implements Arbiter {
         }
 
         public ScriptArbiter build() {
-            AbstractScript script = null;
+            Script script = null;
             for (final Node child : node.getChildren()) {
                 final PluginType<?> type = child.getType();
                 if (type == null) {
                     LOGGER.error("Node {} is missing a Plugintype", 
child.getName());
                     continue;
                 }
-                if 
(AbstractScript.class.isAssignableFrom(type.getPluginClass())) {
-                    script = (AbstractScript) 
configuration.createPluginObject(type, child);
+                if (Script.class.isAssignableFrom(type.getPluginClass())) {
+                    script = (Script) configuration.createPluginObject(type, 
child);
                     node.getChildren().remove(child);
                     break;
                 }
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFileFilterTest.java
 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/factory/ScriptManagerFactoryImpl.java
similarity index 58%
copy from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFileFilterTest.java
copy to 
log4j-script/src/main/java/org/apache/logging/log4j/script/factory/ScriptManagerFactoryImpl.java
index fca3e96..18887d5 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFileFilterTest.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/factory/ScriptManagerFactoryImpl.java
@@ -14,10 +14,21 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.filter;
+package org.apache.logging.log4j.script.factory;
 
-import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.script.ScriptManager;
+import org.apache.logging.log4j.core.script.ScriptManagerFactory;
+import org.apache.logging.log4j.core.util.WatchManager;
+import org.apache.logging.log4j.script.ScriptManagerImpl;
 
-@LoggerContextSource("log4j-scriptFile-filters.xml")
-public class ScriptFileFilterTest extends AbstractScriptFilterTest {
+/**
+ * Creates a ScriptManager.
+ */
+public class ScriptManagerFactoryImpl implements ScriptManagerFactory {
+
+    @Override
+    public ScriptManager createScriptManager(Configuration configuration, 
WatchManager watchManager) {
+        return new ScriptManagerImpl(configuration, watchManager);
+    }
 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ScriptFilter.java
 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/filter/ScriptFilter.java
similarity index 86%
rename from 
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ScriptFilter.java
rename to 
log4j-script/src/main/java/org/apache/logging/log4j/script/filter/ScriptFilter.java
index 14b7f84..8e793a6 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ScriptFilter.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/filter/ScriptFilter.java
@@ -14,27 +14,29 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.filter;
-
-import javax.script.SimpleBindings;
+package org.apache.logging.log4j.script.filter;
 
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.AbstractLifeCycle;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.Logger;
 import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.filter.AbstractFilter;
+import org.apache.logging.log4j.core.script.Script;
+import org.apache.logging.log4j.core.script.ScriptBindings;
 import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginAttribute;
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
 import org.apache.logging.log4j.plugins.PluginElement;
 import org.apache.logging.log4j.plugins.PluginFactory;
-import org.apache.logging.log4j.core.script.AbstractScript;
-import org.apache.logging.log4j.core.script.ScriptRef;
 import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.message.ObjectMessage;
 import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.script.ScriptManagerImpl;
+import org.apache.logging.log4j.script.ScriptRef;
 import org.apache.logging.log4j.status.StatusLogger;
 
 /**
@@ -45,10 +47,10 @@ public final class ScriptFilter extends AbstractFilter {
 
     private static final org.apache.logging.log4j.Logger logger = 
StatusLogger.getLogger();
 
-    private final AbstractScript script;
+    private final Script script;
     private final Configuration configuration;
 
-    private ScriptFilter(final AbstractScript script, final Configuration 
configuration, final Result onMatch,
+    private ScriptFilter(final Script script, final Configuration 
configuration, final Result onMatch,
                          final Result onMismatch) {
         super(onMatch, onMismatch);
         this.script = script;
@@ -61,7 +63,7 @@ public final class ScriptFilter extends AbstractFilter {
     @Override
     public Result filter(final Logger logger, final Level level, final Marker 
marker, final String msg,
                          final Object... params) {
-        final SimpleBindings bindings = new SimpleBindings();
+        final ScriptBindings bindings = ScriptManagerImpl.createBindings();
         bindings.put("logger", logger);
         bindings.put("level", level);
         bindings.put("marker", marker);
@@ -77,7 +79,7 @@ public final class ScriptFilter extends AbstractFilter {
     @Override
     public Result filter(final Logger logger, final Level level, final Marker 
marker, final Object msg,
                          final Throwable t) {
-        final SimpleBindings bindings = new SimpleBindings();
+        final ScriptBindings bindings = ScriptManagerImpl.createBindings();
         bindings.put("logger", logger);
         bindings.put("level", level);
         bindings.put("marker", marker);
@@ -93,7 +95,7 @@ public final class ScriptFilter extends AbstractFilter {
     @Override
     public Result filter(final Logger logger, final Level level, final Marker 
marker, final Message msg,
                          final Throwable t) {
-        final SimpleBindings bindings = new SimpleBindings();
+        final ScriptBindings bindings = ScriptManagerImpl.createBindings();
         bindings.put("logger", logger);
         bindings.put("level", level);
         bindings.put("marker", marker);
@@ -108,7 +110,7 @@ public final class ScriptFilter extends AbstractFilter {
 
     @Override
     public Result filter(final LogEvent event) {
-        final SimpleBindings bindings = new SimpleBindings();
+        final ScriptBindings bindings = ScriptManagerImpl.createBindings();
         bindings.put("logEvent", event);
         bindings.putAll(configuration.getProperties());
         bindings.put("substitutor", configuration.getStrSubstitutor());
@@ -133,13 +135,13 @@ public final class ScriptFilter extends AbstractFilter {
     // TODO Consider refactoring to use AbstractFilter.AbstractFilterBuilder
     @PluginFactory
     public static ScriptFilter createFilter(
-            @PluginElement final AbstractScript script,
+            @PluginElement final Script script,
             @PluginAttribute final Result onMatch,
             @PluginAttribute final Result onMismatch,
             @PluginConfiguration final Configuration configuration) {
 
         if (script == null) {
-            LOGGER.error("A Script, ScriptFile or ScriptRef element must be 
provided for this ScriptFilter");
+            AbstractLifeCycle.LOGGER.error("A Script, ScriptFile or ScriptRef 
element must be provided for this ScriptFilter");
             return null;
         }
         if (script instanceof ScriptRef) {
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/ScriptPatternSelector.java
 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/layout/ScriptPatternSelector.java
similarity index 94%
rename from 
log4j-core/src/main/java/org/apache/logging/log4j/core/layout/ScriptPatternSelector.java
rename to 
log4j-script/src/main/java/org/apache/logging/log4j/script/layout/ScriptPatternSelector.java
index b281377..0828756 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/ScriptPatternSelector.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/layout/ScriptPatternSelector.java
@@ -14,21 +14,26 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.layout;
+package org.apache.logging.log4j.script.layout;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.layout.PatternMatch;
+import org.apache.logging.log4j.core.layout.PatternSelector;
 import org.apache.logging.log4j.core.pattern.PatternFormatter;
 import org.apache.logging.log4j.core.pattern.PatternParser;
-import org.apache.logging.log4j.core.script.AbstractScript;
-import org.apache.logging.log4j.core.script.ScriptRef;
+import org.apache.logging.log4j.core.script.ScriptBindings;
 import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginBuilderAttribute;
 import org.apache.logging.log4j.plugins.PluginElement;
 import org.apache.logging.log4j.plugins.PluginFactory;
+import org.apache.logging.log4j.script.AbstractScript;
+import org.apache.logging.log4j.script.ScriptManagerImpl;
+import org.apache.logging.log4j.script.ScriptRef;
 import org.apache.logging.log4j.status.StatusLogger;
 
 import javax.script.SimpleBindings;
@@ -189,7 +194,7 @@ public class ScriptPatternSelector implements 
PatternSelector {
 
     @Override
     public PatternFormatter[] getFormatters(final LogEvent event) {
-        final SimpleBindings bindings = new SimpleBindings();
+        final ScriptBindings bindings = ScriptManagerImpl.createBindings();
         bindings.putAll(configuration.getProperties());
         bindings.put("substitutor", configuration.getStrSubstitutor());
         bindings.put("logEvent", event);
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
 b/log4j-script/src/main/java/org/apache/logging/log4j/script/package-info.java
similarity index 94%
rename from 
log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
rename to 
log4j-script/src/main/java/org/apache/logging/log4j/script/package-info.java
index 4964b30..46a4bba 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/script/package-info.java
+++ 
b/log4j-script/src/main/java/org/apache/logging/log4j/script/package-info.java
@@ -17,4 +17,4 @@
 /**
  * Log4j 2 Script support.
  */
-package org.apache.logging.log4j.core.script;
+package org.apache.logging.log4j.script;
diff --git 
a/log4j-script/src/main/resources/META-INF/services/org.apache.logging.log4j.core.script.ScriptManagerFactory
 
b/log4j-script/src/main/resources/META-INF/services/org.apache.logging.log4j.core.script.ScriptManagerFactory
new file mode 100644
index 0000000..01db40a
--- /dev/null
+++ 
b/log4j-script/src/main/resources/META-INF/services/org.apache.logging.log4j.core.script.ScriptManagerFactory
@@ -0,0 +1 @@
+org.apache.logging.log4j.script.factory.ScriptManagerFactoryImpl
\ No newline at end of file
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ScriptAppenderSelectorTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/ScriptAppenderSelectorTest.java
similarity index 98%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ScriptAppenderSelectorTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/appender/ScriptAppenderSelectorTest.java
index 0a175b2..4d70fc4 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ScriptAppenderSelectorTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/ScriptAppenderSelectorTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.appender;
+package org.apache.logging.log4j.script.appender;
 
 import org.apache.logging.log4j.MarkerManager;
 import org.apache.logging.log4j.core.config.Configuration;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDeleteScriptFri13thTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/rolling/RollingAppenderDeleteScriptFri13thTest.java
similarity index 98%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDeleteScriptFri13thTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/appender/rolling/RollingAppenderDeleteScriptFri13thTest.java
index f192b4d..156a8d3 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDeleteScriptFri13thTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/rolling/RollingAppenderDeleteScriptFri13thTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.appender.rolling;
+package org.apache.logging.log4j.script.appender.rolling;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDeleteScriptTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/rolling/RollingAppenderDeleteScriptTest.java
similarity index 97%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDeleteScriptTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/appender/rolling/RollingAppenderDeleteScriptTest.java
index e218f6b..3de0996 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDeleteScriptTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/rolling/RollingAppenderDeleteScriptTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.appender.rolling;
+package org.apache.logging.log4j.script.appender.rolling;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptConditionTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/rolling/action/ScriptConditionTest.java
similarity index 88%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptConditionTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/appender/rolling/action/ScriptConditionTest.java
index a2f14b9..5374db7 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptConditionTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/rolling/action/ScriptConditionTest.java
@@ -15,11 +15,13 @@
  * limitations under the license.
  */
 
-package org.apache.logging.log4j.core.appender.rolling.action;
+package org.apache.logging.log4j.script.appender.rolling.action;
 
+import 
org.apache.logging.log4j.core.appender.rolling.action.PathWithAttributes;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.DefaultConfiguration;
-import org.apache.logging.log4j.core.script.Script;
+import 
org.apache.logging.log4j.core.test.appender.rolling.action.DummyFileAttributes;
+import org.apache.logging.log4j.script.ScriptPlugin;
 import org.junit.jupiter.api.Tag;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledForJreRange;
@@ -45,7 +47,7 @@ public class ScriptConditionTest {
     @Test
     public void testConstructorDisallowsNullConfig() {
         assertThrows(NullPointerException.class,
-                () -> new ScriptCondition(new Script("test", "js", 
"print('hi')"), null));
+                () -> new ScriptCondition(new ScriptPlugin("test", "js", 
"print('hi')"), null));
     }
 
     @Test
@@ -56,7 +58,7 @@ public class ScriptConditionTest {
     @Test
     public void testCreateConditionDisallowsNullConfig() {
         assertThrows(NullPointerException.class, () -> 
ScriptCondition.createCondition(
-                new Script("test", "js", "print('hi')"), null));
+                new ScriptPlugin("test", "js", "print('hi')"), null));
     }
 
     @Test
@@ -65,7 +67,7 @@ public class ScriptConditionTest {
         final Configuration config = new DefaultConfiguration();
         config.initialize(); // creates the ScriptManager
 
-        final Script script = new Script("test", "javascript", "pathList;"); 
// script that returns pathList
+        final ScriptPlugin script = new ScriptPlugin("test", "javascript", 
"pathList;"); // script that returns pathList
         final ScriptCondition condition = new ScriptCondition(script, config);
         final List<PathWithAttributes> pathList = new ArrayList<>();
         final Path base = Paths.get("baseDirectory");
@@ -86,7 +88,7 @@ public class ScriptConditionTest {
 
         final String scriptText = "pathList.remove(1);" //
                 + "pathList;";
-        final Script script = new Script("test", "javascript", scriptText);
+        final ScriptPlugin script = new ScriptPlugin("test", "javascript", 
scriptText);
         final ScriptCondition condition = new ScriptCondition(script, config);
         final Path base = Paths.get("baseDirectory");
         final List<PathWithAttributes> result = 
condition.selectFilesToDelete(base, pathList);
@@ -128,7 +130,7 @@ public class ScriptConditionTest {
                 + "}" //
                 + "println copy;"
                 + "copy;";
-        final Script script = new Script("test", "groovy", scriptText);
+        final ScriptPlugin script = new ScriptPlugin("test", "groovy", 
scriptText);
         final ScriptCondition condition = new ScriptCondition(script, config);
         final Path base = Paths.get("/path");
         final List<PathWithAttributes> result = 
condition.selectFilesToDelete(base, pathList);
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/routing/DefaultRouteScriptAppenderTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/routing/DefaultRouteScriptAppenderTest.java
similarity index 97%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/routing/DefaultRouteScriptAppenderTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/appender/routing/DefaultRouteScriptAppenderTest.java
index 1500342..01cd51f 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/routing/DefaultRouteScriptAppenderTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/routing/DefaultRouteScriptAppenderTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.appender.routing;
+package org.apache.logging.log4j.script.appender.routing;
 
 import java.util.Map;
 import java.util.concurrent.ConcurrentMap;
@@ -22,6 +22,7 @@ import java.util.concurrent.ConcurrentMap;
 import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.MarkerManager;
 import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.appender.routing.RoutingAppender;
 import org.apache.logging.log4j.core.config.AppenderControl;
 import org.apache.logging.log4j.core.test.junit.LoggerContextRule;
 import org.apache.logging.log4j.core.test.appender.ListAppender;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutesScriptAppenderTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/routing/RoutesScriptAppenderTest.java
similarity index 92%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutesScriptAppenderTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/appender/routing/RoutesScriptAppenderTest.java
index f092692..e7dd240 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutesScriptAppenderTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/appender/routing/RoutesScriptAppenderTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.appender.routing;
+package org.apache.logging.log4j.script.appender.routing;
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertEquals;
@@ -26,6 +26,8 @@ import java.util.concurrent.ConcurrentMap;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.MarkerManager;
+import org.apache.logging.log4j.core.appender.routing.Routes;
+import org.apache.logging.log4j.core.appender.routing.RoutingAppender;
 import org.apache.logging.log4j.core.test.categories.Scripts;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.Logger;
@@ -48,10 +50,10 @@ public class RoutesScriptAppenderTest {
     public static Object[][] getParameters() {
         // @formatter:off
         return new Object[][] {
-            { "log4j-routing-routes-script-groovy.xml", false },
-            { "log4j-routing-routes-script-javascript.xml", false },
-            { "log4j-routing-script-staticvars-javascript.xml", true },
-            { "log4j-routing-script-staticvars-groovy.xml", true },
+            {"log4j-routing-routes-script-groovy.xml", false },
+            {"log4j-routing-routes-script-javascript.xml", false },
+            {"log4j-routing-script-staticvars-javascript.xml", true },
+            {"log4j-routing-script-staticvars-groovy.xml", true },
         };
         // @formatter:on
     }
diff --git 
a/log4j-script/src/test/java/org/apache/logging/log4j/script/config/TestConfigurator.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/config/TestConfigurator.java
new file mode 100644
index 0000000..e0ed655
--- /dev/null
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/config/TestConfigurator.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.script.config;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.ConsoleAppender;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.Configurator;
+import 
org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
+import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
+import 
org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
+import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.logging.log4j.core.test.hamcrest.MapMatchers.hasSize;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * Test Configuration
+ */
+public class TestConfigurator {
+    @Test
+    public void testBuilderWithScripts() throws Exception {
+        final String script = "if 
(logEvent.getLoggerName().equals(\"NoLocation\")) {\n" +
+                "                return \"NoLocation\";\n" +
+                "            } else if (logEvent.getMarker() != null && 
logEvent.getMarker().isInstanceOf(\"FLOW\")) {\n" +
+                "                return \"Flow\";\n" +
+                "            } else {\n" +
+                "                return null;\n" +
+                "            }";
+        final ConfigurationBuilder<BuiltConfiguration> builder = 
ConfigurationBuilderFactory.newConfigurationBuilder();
+        builder.setStatusLevel(Level.ERROR);
+        builder.setConfigurationName("BuilderTest");
+        builder.add(builder.newScriptFile("filter.groovy", 
"target/test-classes/scripts/filter.groovy").addIsWatched(true));
+        final AppenderComponentBuilder appenderBuilder = 
builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
+                ConsoleAppender.Target.SYSTEM_OUT);
+        appenderBuilder.add(builder.newLayout("PatternLayout").
+                addComponent(builder.newComponent("ScriptPatternSelector")
+                        .addAttribute("defaultPattern", "[%-5level] %c{1.} 
%C{1.}.%M.%L %msg%n")
+                        
.addComponent(builder.newComponent("PatternMatch").addAttribute("key", 
"NoLocation")
+                                .addAttribute("pattern", "[%-5level] %c{1.} 
%msg%n"))
+                        
.addComponent(builder.newComponent("PatternMatch").addAttribute("key", "FLOW")
+                                .addAttribute("pattern", "[%-5level] %c{1.} 
====== %C{1.}.%M:%L %msg ======%n"))
+                        .addComponent(builder.newComponent("selectorScript", 
"Script", script).addAttribute("language", "beanshell"))));
+        appenderBuilder.add(builder.newFilter("ScriptFilter", 
Filter.Result.DENY,
+                
Filter.Result.NEUTRAL).addComponent(builder.newComponent("ScriptRef").addAttribute("ref",
 "filter.groovy")));
+        builder.add(appenderBuilder);
+        builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG).
+                add(builder.newAppenderRef("Stdout")).
+                addAttribute("additivity", false));
+        
builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
+        LoggerContext ctx = Configurator.initialize(builder.build());
+        final Configuration config = ctx.getConfiguration();
+        assertNotNull(config, "No configuration");
+        assertEquals("BuilderTest", config.getName(), "Unexpected 
Configuration");
+        assertThat(config.getAppenders(), hasSize(equalTo(1)));
+        assertNotNull(config.getScriptManager().getScript("filter.groovy"), 
"Filter script not found");
+        assertNotNull(config.getScriptManager().getScript("selectorScript"), 
"pattern selector script not found");
+    }
+}
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/arbiters/ScriptArbiterTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/config/arbiter/ScriptArbiterTest.java
similarity index 97%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/arbiters/ScriptArbiterTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/config/arbiter/ScriptArbiterTest.java
index c64cfe8..b293dfa 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/arbiters/ScriptArbiterTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/config/arbiter/ScriptArbiterTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.config.arbiters;
+package org.apache.logging.log4j.script.config.arbiter;
 
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.LoggerContext;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/AbstractScriptFilterTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/filter/AbstractScriptFilterTest.java
similarity index 98%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/AbstractScriptFilterTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/filter/AbstractScriptFilterTest.java
index 155a314..20a5e8b 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/AbstractScriptFilterTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/filter/AbstractScriptFilterTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.filter;
+package org.apache.logging.log4j.script.filter;
 
 import java.util.List;
 
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFileFilterPropertiesTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptFileFilterPropertiesTest.java
similarity index 95%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFileFilterPropertiesTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptFileFilterPropertiesTest.java
index 1afc3c0..6bee68c 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFileFilterPropertiesTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptFileFilterPropertiesTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.filter;
+package org.apache.logging.log4j.script.filter;
 
 import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
 
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFileFilterTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptFileFilterTest.java
similarity index 95%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFileFilterTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptFileFilterTest.java
index fca3e96..0e79b70 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFileFilterTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptFileFilterTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.filter;
+package org.apache.logging.log4j.script.filter;
 
 import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
 
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFilterTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptFilterTest.java
similarity index 95%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFilterTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptFilterTest.java
index 368d438..9beac81 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptFilterTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptFilterTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.filter;
+package org.apache.logging.log4j.script.filter;
 
 import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
 
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptRefFilterTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptRefFilterTest.java
similarity index 95%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptRefFilterTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptRefFilterTest.java
index 9a07f24..0397858 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/ScriptRefFilterTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/filter/ScriptRefFilterTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core.filter;
+package org.apache.logging.log4j.script.filter;
 
 import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
 
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/PatternSelectorTest.java
 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/layout/PatternSelectorTest.java
similarity index 87%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/PatternSelectorTest.java
rename to 
log4j-script/src/test/java/org/apache/logging/log4j/script/layout/PatternSelectorTest.java
index afc91aa..c29779b 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/PatternSelectorTest.java
+++ 
b/log4j-script/src/test/java/org/apache/logging/log4j/script/layout/PatternSelectorTest.java
@@ -14,7 +14,7 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.logging.log4j.core;
+package org.apache.logging.log4j.script.layout;
 
 import java.util.List;
 
@@ -43,7 +43,7 @@ public class PatternSelectorTest {
         assertEquals(3, messages.size(),
                 "Incorrect number of messages. Expected 3, Actual " + 
messages.size() + ": " + messages);
         final String expect = String.format("[TRACE] TestMarkerPatternSelector 
====== "
-                + "o.a.l.l.c.PatternSelectorTest.testMarkerPatternSelector:38 
Enter ======%n");
+                + 
"o.a.l.l.s.l.PatternSelectorTest.testMarkerPatternSelector:38 Enter ======%n");
         assertEquals(expect, messages.get(0));
         assertEquals("[INFO ] TestMarkerPatternSelector Hello World" + 
Strings.LINE_SEPARATOR, messages.get(1));
         app.clear();
@@ -63,9 +63,9 @@ public class PatternSelectorTest {
         assertEquals(4, messages.size(),
                 "Incorrect number of messages. Expected 4, Actual " + 
messages.size() + ": " + messages);
         String expect = "[TRACE] TestScriptPatternSelector ====== " +
-                "o.a.l.l.c.PatternSelectorTest.testScriptPatternSelector:57 
Enter ======" + Strings.LINE_SEPARATOR;
+                "o.a.l.l.s.l.PatternSelectorTest.testScriptPatternSelector:57 
Enter ======" + Strings.LINE_SEPARATOR;
         assertEquals(expect, messages.get(0));
-        expect = "[INFO ] TestScriptPatternSelector 
o.a.l.l.c.PatternSelectorTest.testScriptPatternSelector.58 " +
+        expect = "[INFO ] TestScriptPatternSelector 
o.a.l.l.s.l.PatternSelectorTest.testScriptPatternSelector.58 " +
                 "Hello World" + Strings.LINE_SEPARATOR;
         assertEquals(expect, messages.get(1));
         assertEquals("[INFO ] NoLocation No location information" + 
Strings.LINE_SEPARATOR, messages.get(2));
@@ -86,10 +86,10 @@ public class PatternSelectorTest {
         assertEquals(4, messages.size(),
                 "Incorrect number of messages. Expected 4, Actual " + 
messages.size() + ": " + messages);
         String expect = "[TRACE] TestJavaScriptPatternSelector ====== " +
-                
"o.a.l.l.c.PatternSelectorTest.testJavaScriptPatternSelector:80 Enter ======" + 
Strings.LINE_SEPARATOR;
+                
"o.a.l.l.s.l.PatternSelectorTest.testJavaScriptPatternSelector:80 Enter ======" 
+ Strings.LINE_SEPARATOR;
         assertEquals(expect, messages.get(0));
         expect = "[INFO ] TestJavaScriptPatternSelector " +
-                
"o.a.l.l.c.PatternSelectorTest.testJavaScriptPatternSelector.81 Hello World" + 
Strings.LINE_SEPARATOR;
+                
"o.a.l.l.s.l.PatternSelectorTest.testJavaScriptPatternSelector.81 Hello World" 
+ Strings.LINE_SEPARATOR;
         assertEquals(expect, messages.get(1));
         assertEquals("[INFO ] JavascriptNoLocation No location information" + 
Strings.LINE_SEPARATOR, messages.get(2));
         app.clear();
diff --git 
a/log4j-core-test/src/test/resources/log4j-appender-selector-groovy.xml 
b/log4j-script/src/test/resources/log4j-appender-selector-groovy.xml
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-appender-selector-groovy.xml
rename to log4j-script/src/test/resources/log4j-appender-selector-groovy.xml
diff --git 
a/log4j-core-test/src/test/resources/log4j-appender-selector-javascript.xml 
b/log4j-script/src/test/resources/log4j-appender-selector-javascript.xml
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-appender-selector-javascript.xml
rename to log4j-script/src/test/resources/log4j-appender-selector-javascript.xml
diff --git a/log4j-core-test/src/test/resources/log4j-patternSelector.xml 
b/log4j-script/src/test/resources/log4j-patternSelector.xml
similarity index 100%
rename from log4j-core-test/src/test/resources/log4j-patternSelector.xml
rename to log4j-script/src/test/resources/log4j-patternSelector.xml
diff --git 
a/log4j-core-test/src/test/resources/log4j-rolling-with-custom-delete-script-fri13th.xml
 
b/log4j-script/src/test/resources/log4j-rolling-with-custom-delete-script-fri13th.xml
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-rolling-with-custom-delete-script-fri13th.xml
rename to 
log4j-script/src/test/resources/log4j-rolling-with-custom-delete-script-fri13th.xml
diff --git 
a/log4j-core-test/src/test/resources/log4j-rolling-with-custom-delete-script.xml
 b/log4j-script/src/test/resources/log4j-rolling-with-custom-delete-script.xml
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-rolling-with-custom-delete-script.xml
rename to 
log4j-script/src/test/resources/log4j-rolling-with-custom-delete-script.xml
diff --git 
a/log4j-core-test/src/test/resources/log4j-routing-default-route-script-groovy.xml
 b/log4j-script/src/test/resources/log4j-routing-default-route-script-groovy.xml
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-routing-default-route-script-groovy.xml
rename to 
log4j-script/src/test/resources/log4j-routing-default-route-script-groovy.xml
diff --git 
a/log4j-core-test/src/test/resources/log4j-routing-default-route-script-javascript.xml
 
b/log4j-script/src/test/resources/log4j-routing-default-route-script-javascript.xml
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-routing-default-route-script-javascript.xml
rename to 
log4j-script/src/test/resources/log4j-routing-default-route-script-javascript.xml
diff --git 
a/log4j-core-test/src/test/resources/log4j-routing-routes-script-groovy.xml 
b/log4j-script/src/test/resources/log4j-routing-routes-script-groovy.xml
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-routing-routes-script-groovy.xml
rename to log4j-script/src/test/resources/log4j-routing-routes-script-groovy.xml
diff --git 
a/log4j-core-test/src/test/resources/log4j-routing-routes-script-javascript.xml 
b/log4j-script/src/test/resources/log4j-routing-routes-script-javascript.xml
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-routing-routes-script-javascript.xml
rename to 
log4j-script/src/test/resources/log4j-routing-routes-script-javascript.xml
diff --git 
a/log4j-core-test/src/test/resources/log4j-routing-script-staticvars-groovy.xml 
b/log4j-script/src/test/resources/log4j-routing-script-staticvars-groovy.xml
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-routing-script-staticvars-groovy.xml
rename to 
log4j-script/src/test/resources/log4j-routing-script-staticvars-groovy.xml
diff --git 
a/log4j-core-test/src/test/resources/log4j-routing-script-staticvars-javascript.xml
 
b/log4j-script/src/test/resources/log4j-routing-script-staticvars-javascript.xml
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-routing-script-staticvars-javascript.xml
rename to 
log4j-script/src/test/resources/log4j-routing-script-staticvars-javascript.xml
diff --git a/log4j-core-test/src/test/resources/log4j-script-filters.xml 
b/log4j-script/src/test/resources/log4j-script-filters.xml
similarity index 100%
rename from log4j-core-test/src/test/resources/log4j-script-filters.xml
rename to log4j-script/src/test/resources/log4j-script-filters.xml
diff --git 
a/log4j-core-test/src/test/resources/log4j-scriptFile-filters.properties 
b/log4j-script/src/test/resources/log4j-scriptFile-filters.properties
similarity index 100%
rename from 
log4j-core-test/src/test/resources/log4j-scriptFile-filters.properties
rename to log4j-script/src/test/resources/log4j-scriptFile-filters.properties
diff --git a/log4j-core-test/src/test/resources/log4j-scriptFile-filters.xml 
b/log4j-script/src/test/resources/log4j-scriptFile-filters.xml
similarity index 100%
rename from log4j-core-test/src/test/resources/log4j-scriptFile-filters.xml
rename to log4j-script/src/test/resources/log4j-scriptFile-filters.xml
diff --git a/log4j-core-test/src/test/resources/log4j-scriptRef-filters.xml 
b/log4j-script/src/test/resources/log4j-scriptRef-filters.xml
similarity index 100%
rename from log4j-core-test/src/test/resources/log4j-scriptRef-filters.xml
rename to log4j-script/src/test/resources/log4j-scriptRef-filters.xml
diff --git a/log4j-core-test/src/test/resources/log4j2-scriptArbiters.xml 
b/log4j-script/src/test/resources/log4j2-scriptArbiters.xml
similarity index 100%
rename from log4j-core-test/src/test/resources/log4j2-scriptArbiters.xml
rename to log4j-script/src/test/resources/log4j2-scriptArbiters.xml
diff --git a/log4j-core-test/src/test/resources/scripts/filter.groovy 
b/log4j-script/src/test/resources/scripts/filter.groovy
similarity index 84%
rename from log4j-core-test/src/test/resources/scripts/filter.groovy
rename to log4j-script/src/test/resources/scripts/filter.groovy
index ef6998b..72f98e7 100644
--- a/log4j-core-test/src/test/resources/scripts/filter.groovy
+++ b/log4j-script/src/test/resources/scripts/filter.groovy
@@ -1 +1,3 @@
+package scripts
+
 return logEvent.marker?.isInstanceOf('FLOW') || 
logEvent.contextData.containsKey('UserId')
diff --git a/log4j-core-test/src/test/resources/scripts/filter.js 
b/log4j-script/src/test/resources/scripts/filter.js
similarity index 100%
rename from log4j-core-test/src/test/resources/scripts/filter.js
rename to log4j-script/src/test/resources/scripts/filter.js
diff --git a/pom.xml b/pom.xml
index 2ae785f..6e9b535 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1740,6 +1740,7 @@
     <module>log4j-jpl</module>
     <module>log4j-liquibase</module>
     <module>log4j-appserver</module>
+    <module>log4j-script</module>
     <module>log4j-smtp</module>
     <module>log4j-osgi</module>
     <module>log4j-docker</module>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 187d6bd..943fadc 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,9 @@
          - "remove" - Removed
     -->
     <release version="3.0.0" date="2021-MM-DD" description="GA Release 3.0.0">
+      <action issue="LOG4J2-3307" dev="rgoers" type="update">
+        Move Scripting to its own module.
+      </action>
       <action issue="LOG4J2-3242" dev="rgoers" type="fix">
         Move JNDI to its own module.
       </action>
diff --git a/src/site/asciidoc/manual/appenders.adoc 
b/src/site/asciidoc/manual/appenders.adoc
index f19195e..a246de6 100644
--- a/src/site/asciidoc/manual/appenders.adoc
+++ b/src/site/asciidoc/manual/appenders.adoc
@@ -4107,7 +4107,7 @@ Appender in a link:#FailoverAppender[FailoverAppender].
 == ScriptAppenderSelector
 
 When the configuration is built, the `ScriptAppenderSelector` appender
-calls a `Script` to compute an appender name. Log4j then creates one of
+calls a `ScriptPlugin` to compute an appender name. Log4j then creates one of
 the appender named listed under `AppenderSet` using the name of the
 `ScriptAppenderSelector`. After configuration, Log4j ignores the
 `ScriptAppenderSelector`. Log4j only builds the one selected appender
diff --git a/src/site/asciidoc/manual/filters.adoc 
b/src/site/asciidoc/manual/filters.adoc
index 5a61201..7a1ade7 100644
--- a/src/site/asciidoc/manual/filters.adoc
+++ b/src/site/asciidoc/manual/filters.adoc
@@ -580,7 +580,7 @@ Throwable as part of the Message.
 The sample below shows how to declare script fields and then reference
 them in specific components. See
 link:appenders.html#ScriptCondition[ScriptCondition] for an example of
-how the `Script` element can be used to embed script code directly in
+how the `ScriptPlugin` element can be used to embed script code directly in
 the configuration.
 
 [source,xml]

Reply via email to