diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ScriptConfigurationTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ScriptConfigurationTest.java new file mode 100644 index 00000000000..7e5871fa77d --- /dev/null +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ScriptConfigurationTest.java @@ -0,0 +1,60 @@ +/* + * 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.core.appender; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.apache.logging.log4j.core.test.junit.LoggerContextSource; +import org.apache.logging.log4j.spi.ExtendedLogger; +import org.apache.logging.log4j.core.script.ScriptRef; // Correct import for ScriptRef +import org.apache.logging.log4j.core.config.Configuration; // Import for Configuration +import org.junit.jupiter.api.Test; + +@LoggerContextSource("log4j-script-ref-test.xml") +class ScriptConfigurationTest { + + @Test + void testScriptRefConfiguration(final Configuration configuration) { + // Verify that the main Scripts element is initialized + assertNotNull(configuration.getScriptManager(), "ScriptManager should not be null"); + + // Verify a ScriptRef element is correctly resolved + ScriptRef scriptRef = (ScriptRef) configuration.getScriptManager().getScript("ExampleScriptRef"); + assertNotNull(scriptRef, "ScriptRef should not be null"); + assertThat(scriptRef.getLanguage(), containsString("groovy")); + assertThat(scriptRef.getScriptText(), containsString("return \"Hello, Log4j!\";")); + + // Ensure that the script executes correctly + Object result = configuration.getScriptManager().execute("ExampleScriptRef", null); + assertNotNull(result, "Script execution result should not be null"); + assertThat(result.toString(), containsString("Hello, Log4j!")); + + // Verify that the console appender is initialized + final ConsoleAppender consoleAppender = (ConsoleAppender) configuration.getAppender("Console"); + assertNotNull(consoleAppender, "Console appender should be initialized"); + + // Verify that the log messages are printed to the console + ExtendedLogger logger = configuration.getLoggerContext().getLogger(ScriptConfigurationTest.class); + logger.info("Test message"); + + // Capture console output (depending on test framework, this might need a mock or special handling) + // Check if the expected log message is printed in the console output + assertThat(consoleAppender.getLayout().toString(), containsString("Test message")); + } +} diff --git a/log4j-core-test/src/test/resources/log4j-script-filters.xml b/log4j-core-test/src/test/resources/log4j-script-filters.xml index 12e88c8bdc6..5708228f63f 100644 --- a/log4j-core-test/src/test/resources/log4j-script-filters.xml +++ b/log4j-core-test/src/test/resources/log4j-script-filters.xml @@ -19,6 +19,7 @@ + diff --git a/log4j-core-test/src/test/resources/log4j-script-ref-test.xml b/log4j-core-test/src/test/resources/log4j-script-ref-test.xml new file mode 100644 index 00000000000..4cee029bfcb --- /dev/null +++ b/log4j-core-test/src/test/resources/log4j-script-ref-test.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + 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 5b60a7727b3..7aaf919978d 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 @@ -574,6 +574,7 @@ protected void preConfigure(final Node node) { /** * Process conditions by evaluating them and including the children of conditions that are true * and discarding those that are not. + * * @param node The node to evaluate. */ protected void processConditionals(final Node node) { @@ -625,6 +626,7 @@ protected void processConditionals(final Node node) { /** * Handle Select nodes. This finds the first child condition that returns true and attaches its children * to the parent of the Select Node. Other Nodes are discarded. + * * @param selectNode The Select Node. * @param type The PluginType of the Select Node. * @return The list of Nodes to be added to the parent. @@ -687,28 +689,35 @@ protected void doConfigure() { configurationStrSubstitutor.setVariableResolver(interpolator); } + for (final Node node : rootNode.getChildren()) { + if ("Scripts".equalsIgnoreCase(node.getName())) { + createConfiguration(node, null); + if (node.getObject() != null) { + for (final AbstractScript script : node.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); + } + } + } + break; + } + } + boolean setLoggers = false; boolean setRoot = false; for (final Node child : rootNode.getChildren()) { - if ("Properties".equalsIgnoreCase(child.getName())) { - // We already used this node - continue; + if ("Properties".equalsIgnoreCase(child.getName()) || "Scripts".equalsIgnoreCase(child.getName())) { + continue; // Skip already processed nodes } createConfiguration(child, null); if (child.getObject() == null) { continue; } - if ("Scripts".equalsIgnoreCase(child.getName())) { - 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); - } - } - } else if ("Appenders".equalsIgnoreCase(child.getName())) { + if ("Appenders".equalsIgnoreCase(child.getName())) { appenders = child.getObject(); } else if (child.isInstanceOf(Filter.class)) { addFilter(child.getObject(Filter.class)); @@ -895,7 +904,8 @@ public ReliabilityStrategy getReliabilityStrategy(final LoggerConfig loggerConfi *

* Note: This method is not used when configuring via configuration. It is primarily used by unit tests. *

- * @param logger The Logger the Appender will be associated with. + * + * @param logger The Logger the Appender will be associated with. * @param appender The Appender. */ @Override @@ -925,6 +935,7 @@ public synchronized void addLoggerAppender( *

* Note: This method is not used when configuring via configuration. It is primarily used by unit tests. *

+ * * @param logger The Logger the Footer will be associated with. * @param filter The Filter. */ @@ -950,7 +961,8 @@ public synchronized void addLoggerFilter(final org.apache.logging.log4j.core.Log *

* Note: This method is not used when configuring via configuration. It is primarily used by unit tests. *

- * @param logger The Logger the Appender will be associated with. + * + * @param logger The Logger the Appender will be associated with. * @param additive True if the LoggerConfig should be additive, false otherwise. */ @Override @@ -1101,6 +1113,7 @@ public void createConfiguration(final Node node, final LogEvent event) { /** * This method is used by Arbiters to create specific children. + * * @param type The PluginType. * @param node The Node. * @return The created object or null; @@ -1144,8 +1157,9 @@ public Object createPluginObject(final PluginType type, final Node node) { * Although the happy path works, more work still needs to be done to log incorrect parameters. These will generally * result in unhelpful InvocationTargetExceptions. *

- * @param type the type of plugin to create. - * @param node the corresponding configuration node for this plugin to create. + * + * @param type the type of plugin to create. + * @param node the corresponding configuration node for this plugin to create. * @param event the LogEvent that spurred the creation of this plugin * @return the created plugin object or {@code null} if there was an error setting it up. * @see org.apache.logging.log4j.core.config.plugins.util.PluginBuilder diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ScriptFilter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ScriptFilter.java index 066dc7aa137..dc528585ca1 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ScriptFilter.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ScriptFilter.java @@ -37,7 +37,8 @@ import org.apache.logging.log4j.status.StatusLogger; /** - * Returns the onMatch result if the script returns True and returns the onMismatch value otherwise. + * Returns the onMatch result if the script returns True and returns the + * onMismatch value otherwise. */ @Plugin(name = "ScriptFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true) public final class ScriptFilter extends AbstractFilter { @@ -122,10 +123,12 @@ public String toString() { /** * Creates the ScriptFilter. - * @param script The script to run. The script must return a boolean value. Either script or scriptFile must be - * provided. - * @param match The action to take if a match occurs. - * @param mismatch The action to take if no match occurs. + * + * @param script The script to run. The script must return a boolean + * value. Either script or scriptFile must be + * provided. + * @param match The action to take if a match occurs. + * @param mismatch The action to take if no match occurs. * @param configuration the configuration * @return A ScriptFilter. */