You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2015/12/05 11:56:44 UTC

[1/5] logging-log4j2 git commit: LOG4J2-435 avoid IOException if file to delete does not exist

Repository: logging-log4j2
Updated Branches:
  refs/heads/master d64c6f4f1 -> 531031345


LOG4J2-435 avoid IOException if file to delete does not exist

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/c01f5bb4
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/c01f5bb4
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/c01f5bb4

Branch: refs/heads/master
Commit: c01f5bb45e1c61b22bd68331fb0d16acb04bc9d7
Parents: d64c6f4
Author: rpopma <rp...@apache.org>
Authored: Sat Dec 5 19:54:30 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sat Dec 5 19:54:30 2015 +0900

----------------------------------------------------------------------
 .../log4j/core/appender/rolling/action/DeletingVisitor.java        | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c01f5bb4/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/DeletingVisitor.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/DeletingVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/DeletingVisitor.java
index dd94589..825e774 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/DeletingVisitor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/DeletingVisitor.java
@@ -83,7 +83,7 @@ public class DeletingVisitor extends SimpleFileVisitor<Path> {
      */
     protected void delete(final Path file) throws IOException {
         LOGGER.trace("Deleting {}", file);
-        Files.delete(file);
+        Files.deleteIfExists(file);
     }
 
     /**


[2/5] logging-log4j2 git commit: LOG4J2-435 added support for ScriptCondition in Delete action

Posted by rp...@apache.org.
LOG4J2-435 added support for ScriptCondition in Delete action

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/1bc44b66
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/1bc44b66
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/1bc44b66

Branch: refs/heads/master
Commit: 1bc44b66b86db518df9ec7b7176227a3d6915244
Parents: c01f5bb
Author: rpopma <rp...@apache.org>
Authored: Sat Dec 5 19:55:30 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sat Dec 5 19:55:30 2015 +0900

----------------------------------------------------------------------
 .../appender/rolling/action/DeleteAction.java   |  78 +++++++++++--
 .../rolling/action/ScriptCondition.java         | 117 +++++++++++++++++++
 2 files changed, 188 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1bc44b66/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/DeleteAction.java
----------------------------------------------------------------------
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 126fb5d..c2c385f 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
@@ -19,6 +19,7 @@ package org.apache.logging.log4j.core.appender.rolling.action;
 
 import java.io.IOException;
 import java.nio.file.FileVisitor;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.List;
 import java.util.Objects;
@@ -39,6 +40,7 @@ public class DeleteAction extends AbstractPathAction {
 
     private final PathSorter pathSorter;
     private final boolean testMode;
+    private final ScriptCondition scriptCondition;
 
     /**
      * Creates a new DeleteAction that starts scanning for files to delete from the specified base path.
@@ -54,13 +56,16 @@ public class DeleteAction extends AbstractPathAction {
      * @param sorter sorts
      * @param pathConditions an array of path filters (if more than one, they all need to accept a path before it is
      *            deleted).
+     * @param scriptCondition
      */
     DeleteAction(final String basePath, final boolean followSymbolicLinks, final int maxDepth, final boolean testMode,
-            final PathSorter sorter, final PathCondition[] pathConditions, final StrSubstitutor subst) {
+            final PathSorter sorter, final PathCondition[] pathConditions, final ScriptCondition scriptCondition,
+            final StrSubstitutor subst) {
         super(basePath, followSymbolicLinks, maxDepth, pathConditions, subst);
         this.testMode = testMode;
         this.pathSorter = Objects.requireNonNull(sorter, "sorter");
-        if (pathConditions == null || pathConditions.length == 0) {
+        this.scriptCondition = scriptCondition;
+        if (scriptCondition == null && (pathConditions == null || pathConditions.length == 0)) {
             LOGGER.error("Missing Delete conditions: unconditional Delete not supported");
             throw new IllegalArgumentException("Unconditional Delete not supported");
         }
@@ -69,15 +74,66 @@ public class DeleteAction extends AbstractPathAction {
     /*
      * (non-Javadoc)
      * 
+     * @see org.apache.logging.log4j.core.appender.rolling.action.AbstractPathAction#execute()
+     */
+    @Override
+    public boolean execute() throws IOException {
+        if (scriptCondition != null) {
+            return executeScript();
+        } else {
+            return super.execute();
+        }
+    }
+
+    private boolean executeScript() throws IOException {
+        final List<PathWithAttributes> selectedForDeletion = callScript();
+        if (selectedForDeletion == null) {
+            LOGGER.trace("Script returned null list (no files to delete)");
+            return true;
+        }
+        deleteSelectedFiles(selectedForDeletion);
+        return true;
+    }
+
+    private List<PathWithAttributes> callScript() throws IOException {
+        final List<PathWithAttributes> sortedPaths = getSortedPaths();
+        trace("Sorted paths:", sortedPaths);
+        final List<PathWithAttributes> result = scriptCondition.selectFilesToDelete(getBasePath(), sortedPaths);
+        return result;
+    }
+
+    private void deleteSelectedFiles(final List<PathWithAttributes> selectedForDeletion) throws IOException {
+        trace("Paths the script selected for deletion:", selectedForDeletion);
+        for (final PathWithAttributes pathWithAttributes : selectedForDeletion) {
+            final Path path = pathWithAttributes == null ? null : pathWithAttributes.getPath();
+            if (isTestMode()) {
+                LOGGER.info("Deleting {} (TEST MODE: file not actually deleted)", path);
+            } else {
+                delete(path);
+            }
+        }
+    }
+
+    /**
+     * Deletes the specified file.
+     * 
+     * @param path the file to delete
+     * @throws IOException if a problem occurred deleting the file
+     */
+    protected void delete(final Path path) throws IOException {
+        LOGGER.trace("Deleting {}", path);
+        Files.deleteIfExists(path);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
      * @see org.apache.logging.log4j.core.appender.rolling.action.AbstractPathAction#execute(FileVisitor)
      */
     @Override
     public boolean execute(final FileVisitor<Path> visitor) throws IOException {
         final List<PathWithAttributes> sortedPaths = getSortedPaths();
-        LOGGER.trace("Sorted paths:");
-        for (PathWithAttributes pathWithAttributes : sortedPaths) {
-            LOGGER.trace(pathWithAttributes);
-        }
+        trace("Sorted paths:", sortedPaths);
 
         for (PathWithAttributes element : sortedPaths) {
             try {
@@ -91,6 +147,13 @@ public class DeleteAction extends AbstractPathAction {
         return true; // do not abort rollover even if processing failed
     }
 
+    private void trace(final String label, final List<PathWithAttributes> sortedPaths) {
+        LOGGER.trace(label);
+        for (final PathWithAttributes pathWithAttributes : sortedPaths) {
+            LOGGER.trace(pathWithAttributes);
+        }
+    }
+
     /**
      * Returns a sorted list of all files up to maxDepth under the basePath.
      * 
@@ -145,10 +208,11 @@ public class DeleteAction extends AbstractPathAction {
             @PluginAttribute(value = "testMode", defaultBoolean = false) final boolean testMode,
             @PluginElement("PathSorter") final PathSorter sorterParameter,
             @PluginElement("PathConditions") final PathCondition[] pathConditions,
+            @PluginElement("ScriptCondition") final ScriptCondition scriptCondition,
             @PluginConfiguration final Configuration config) {
             // @formatter:on
         final PathSorter sorter = sorterParameter == null ? new PathSortByModificationTime(true) : sorterParameter;
-        return new DeleteAction(basePath, followLinks, maxDepth, testMode, sorter, pathConditions,
+        return new DeleteAction(basePath, followLinks, maxDepth, testMode, sorter, pathConditions, scriptCondition,
                 config.getStrSubstitutor());
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1bc44b66/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptCondition.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptCondition.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptCondition.java
new file mode 100644
index 0000000..c1d4bea
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptCondition.java
@@ -0,0 +1,117 @@
+/*
+ * 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.rolling.action;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Objects;
+
+import javax.script.SimpleBindings;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.script.AbstractScript;
+import org.apache.logging.log4j.core.script.ScriptRef;
+import org.apache.logging.log4j.status.StatusLogger;
+
+/**
+ * A condition of the {@link DeleteAction} where a user-provided script selects the files to delete from a provided
+ * list. The specified script may be a {@link Script}, a {@link ScriptFile} or a {@link ScriptRef}.
+ * 
+ * @see #createCondition(AbstractScript, Configuration)
+ */
+@Plugin(name = "ScriptCondition", category = "Core", printObject = true)
+public class ScriptCondition {
+    private static Logger LOGGER = StatusLogger.getLogger();
+
+    private final AbstractScript script;
+    private final Configuration configuration;
+
+    /**
+     * Constructs a new 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) {
+        this.script = Objects.requireNonNull(script, "script");
+        this.configuration = Objects.requireNonNull(configuration, "configuration");
+        if (!(script instanceof ScriptRef)) {
+            configuration.getScriptManager().addScript(script);
+        }
+    }
+
+    /**
+     * Executes the script
+     * 
+     * @param baseDir
+     * @param candidates
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public List<PathWithAttributes> selectFilesToDelete(final Path basePath, final List<PathWithAttributes> candidates) {
+        final SimpleBindings bindings = new SimpleBindings();
+        bindings.put("basePath", basePath);
+        bindings.put("pathList", candidates);
+        bindings.putAll(configuration.getProperties());
+        bindings.put("substitutor", configuration.getStrSubstitutor());
+        bindings.put("LOGGER", LOGGER);
+        final Object object = configuration.getScriptManager().execute(script.getName(), bindings);
+        return (List<PathWithAttributes>) object;
+    }
+
+    /**
+     * Creates the ScriptCondition.
+     * 
+     * @param script The script to run. This may be a {@link Script}, a {@link ScriptFile} or a {@link ScriptRef}. The
+     *            script must return a {@code List<PathWithAttributes>}. When the script is executed, it is provided the
+     *            following bindings:
+     *            <ul>
+     *            <li>basePath - the directory from where the {@link DeleteAction Delete} action started scanning for
+     *            files to delete. Can be used to relativize the paths in the pathList.</li>
+     *            <li>pathList - a {@code java.util.List} containing {@link PathWithAttribute} objects. (The script is
+     *            free to modify and return this list.)</li>
+     *            <li>substitutor - a {@link StrSubstitutor} that can be used to look up variables embedded in the base
+     *            dir or other properties
+     *            <li>LOGGER - the {@link StatusLogger} that can be used to log events during script execution
+     *            <li>any properties declared in the configuration</li>
+     *            </ul>
+     * @param configuration the configuration
+     * @return A ScriptCondition.
+     */
+    @PluginFactory
+    public static ScriptCondition createCondition(@PluginElement("Script") final AbstractScript script,
+            @PluginConfiguration final Configuration configuration) {
+
+        if (script == null) {
+            LOGGER.error("A Script, ScriptFile or ScriptRef element must be provided for this ScriptCondition");
+            return null;
+        }
+        if (script instanceof ScriptRef) {
+            if (configuration.getScriptManager().getScript(script.getName()) == null) {
+                LOGGER.error("ScriptCondition: No script with name {} has been declared.", script.getName());
+                return null;
+            }
+        }
+        return new ScriptCondition(script, configuration);
+    }
+}


[4/5] logging-log4j2 git commit: LOG4J2-435 constructor needs ScriptCondition parameter

Posted by rp...@apache.org.
LOG4J2-435 constructor needs ScriptCondition parameter

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/4ec4a2af
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/4ec4a2af
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/4ec4a2af

Branch: refs/heads/master
Commit: 4ec4a2afbb1d38a8cf3858e16a4035c81947cada
Parents: 2bd5711
Author: rpopma <rp...@apache.org>
Authored: Sat Dec 5 19:56:39 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sat Dec 5 19:56:39 2015 +0900

----------------------------------------------------------------------
 .../log4j/core/appender/rolling/action/DeleteActionTest.java   | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/4ec4a2af/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/DeleteActionTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/DeleteActionTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/DeleteActionTest.java
index 4f0b36e..4a1f14c 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/DeleteActionTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/DeleteActionTest.java
@@ -45,10 +45,10 @@ public class DeleteActionTest {
     }
 
     private static DeleteAction create(String path, boolean followLinks, int maxDepth, boolean testMode,
-            PathCondition[] filters) {
+            PathCondition[] conditions) {
         Configuration config = new BasicConfigurationFactory().new BasicConfiguration();
-        DeleteAction delete = DeleteAction.createDeleteAction(path, followLinks, maxDepth, testMode, null, filters,
-                config);
+        DeleteAction delete = DeleteAction.createDeleteAction(path, followLinks, maxDepth, testMode, null, conditions,
+                null, config);
         return delete;
     }
 


[5/5] logging-log4j2 git commit: LOG4J2-435 integration test for Delete with ScriptCondition

Posted by rp...@apache.org.
LOG4J2-435 integration test for Delete with ScriptCondition

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/53103134
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/53103134
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/53103134

Branch: refs/heads/master
Commit: 53103134519cff36ba644f0f9706189953f89c1d
Parents: 4ec4a2a
Author: rpopma <rp...@apache.org>
Authored: Sat Dec 5 19:57:03 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sat Dec 5 19:57:03 2015 +0900

----------------------------------------------------------------------
 .../RollingAppenderDeleteScriptTest.java        | 85 ++++++++++++++++++++
 .../log4j-rolling-with-custom-delete-script.xml | 76 +++++++++++++++++
 2 files changed, 161 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/53103134/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDeleteScriptTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDeleteScriptTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDeleteScriptTest.java
new file mode 100644
index 0000000..6f64ebe
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDeleteScriptTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.rolling;
+
+import java.io.File;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExternalResource;
+import org.junit.rules.RuleChain;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class RollingAppenderDeleteScriptTest {
+
+    private static final String CONFIG = "log4j-rolling-with-custom-delete-script.xml";
+    private static final String DIR = "target/rolling-with-delete-script/test";
+
+    private final LoggerContextRule ctx = new LoggerContextRule(CONFIG);
+
+    @Rule
+    public RuleChain chain = RuleChain.outerRule(new ExternalResource() {
+        @Override
+        protected void before() throws Throwable {
+            deleteDir();
+        }
+    }).around(ctx);
+
+    @Test
+    public void testAppender() throws Exception {
+        final Logger logger = ctx.getLogger();
+        // Trigger the rollover
+        for (int i = 0; i < 10; ++i) {
+            // 30 chars per message: each message triggers a rollover
+            logger.debug("This is a test message number " + i); // 30 chars:
+        }
+        Thread.sleep(100); // Allow time for rollover to complete
+
+        final File dir = new File(DIR);
+        assertTrue("Dir " + DIR + " should exist", dir.exists());
+        assertTrue("Dir " + DIR + " should contain files", dir.listFiles().length > 0);
+
+        final File[] files = dir.listFiles();
+        for (File file : files) {
+            System.out.println(file);
+        }
+        for (File file : files) {
+            assertTrue(file.getName() + " starts with 'test-'", file.getName().startsWith("test-"));
+            assertTrue(file.getName() + " ends with '.log'", file.getName().endsWith(".log"));
+            String strIndex = file.getName().substring(5, file.getName().indexOf('.'));
+            int index = Integer.parseInt(strIndex);
+            assertTrue(file + " should have odd index", index % 2 == 1);
+        }
+    }
+
+    private static void deleteDir() {
+        final File dir = new File(DIR);
+        if (dir.exists()) {
+            final File[] files = dir.listFiles();
+            for (final File file : files) {
+                file.delete();
+            }
+            dir.delete();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/53103134/log4j-core/src/test/resources/log4j-rolling-with-custom-delete-script.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-rolling-with-custom-delete-script.xml b/log4j-core/src/test/resources/log4j-rolling-with-custom-delete-script.xml
new file mode 100644
index 0000000..ed6ba7a
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-rolling-with-custom-delete-script.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+
+-->
+<Configuration status="TRACE" name="RollingWithCustomDeleteScriptTest">
+  <Properties>
+    <Property name="base">target/rolling-with-delete-script/</Property>
+  </Properties>
+
+  <Appenders>
+    <RollingFile name="RollingFile" fileName="${base}/rollingtest.log" 
+                   filePattern="${base}/test/test-%i.log">
+      <PatternLayout>
+        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+      </PatternLayout>
+      <Policies>
+        <SizeBasedTriggeringPolicy size="50" />
+      </Policies>
+      <DefaultRolloverStrategy max="100" stopCustomActionsOnError="true">
+        <Delete basePath="${base}/test" maxDepth="1" followLinks="false">
+          <ScriptCondition>
+            <Script name="GroovyCondition" language="groovy"><![CDATA[
+                import java.nio.file.*;
+                
+                def pattern = ~/test-(\d*)\.log/;
+                assert pattern.getClass() == java.util.regex.Pattern;
+                
+                def copy = pathList.collect{it};
+                pathList.each { pathWithAttributes ->
+                  def relative = basePath.relativize pathWithAttributes.path
+                  def str = relative.toString();
+                  LOGGER.trace 'SCRIPT: relative ' + str + " (base=$basePath)";
+                  
+                  // keep only files with odd indexes
+                  
+                  def m = pattern.matcher(str);
+                  if (m.find()) {
+                    def index = m.group(1) as int;
+                    def isOdd = (index % 2) == 1;
+                    if (isOdd) {
+                      copy.remove pathWithAttributes; // remove path with odd index from list to delete
+                      LOGGER.trace 'SCRIPT: not deleting path ' + pathWithAttributes;
+                    }
+                  }
+                }
+                LOGGER.trace 'SCRIPT: returning' + copy;
+                copy;
+              ]]>
+            </Script>
+          </ScriptCondition>
+        </Delete>
+      </DefaultRolloverStrategy>
+    </RollingFile>
+  </Appenders>
+
+  <Loggers>
+    <Root level="trace">
+      <AppenderRef ref="RollingFile" />
+    </Root>
+  </Loggers>
+
+</Configuration>
\ No newline at end of file


[3/5] logging-log4j2 git commit: LOG4J2-435 ScriptCondition unit tests

Posted by rp...@apache.org.
LOG4J2-435 ScriptCondition unit tests

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/2bd57119
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/2bd57119
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/2bd57119

Branch: refs/heads/master
Commit: 2bd57119f83b806da95cfb0b0fc5ee5e097ec347
Parents: 1bc44b6
Author: rpopma <rp...@apache.org>
Authored: Sat Dec 5 19:55:51 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sat Dec 5 19:55:51 2015 +0900

----------------------------------------------------------------------
 .../rolling/action/ScriptConditionTest.java     | 130 +++++++++++++++++++
 1 file changed, 130 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/2bd57119/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptConditionTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptConditionTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptConditionTest.java
new file mode 100644
index 0000000..ccbfc86
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/ScriptConditionTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.rolling.action;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+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.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests the ScriptCondition class.
+ */
+public class ScriptConditionTest {
+
+    @Test(expected = NullPointerException.class)
+    public void testConstructorDisallowsNullScript() {
+        new ScriptCondition(null, new DefaultConfiguration());
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testConstructorDisallowsNullConfig() {
+        new ScriptCondition(new Script("test", "js", "print('hi')"), null);
+    }
+
+    @Test
+    public void testCreateConditionReturnsNullForNullScript() {
+        assertNull(ScriptCondition.createCondition(null, new DefaultConfiguration()));
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testCreateConditionDisallowsNullConfig() {
+        ScriptCondition.createCondition(new Script("test", "js", "print('hi')"), null);
+    }
+
+    @Test
+    public void testSelectFilesToDelete() {
+        Configuration config = new DefaultConfiguration();
+        config.initialize(); // creates the ScriptManager
+
+        Script script = new Script("test", "javascript", "pathList;"); // script that returns pathList
+        ScriptCondition condition = new ScriptCondition(script, config);
+        List<PathWithAttributes> pathList = new ArrayList<PathWithAttributes>();
+        Path base = Paths.get("baseDirectory");
+        List<PathWithAttributes> result = condition.selectFilesToDelete(base, pathList);
+        assertSame(result, pathList);
+    }
+
+    @Test
+    public void testSelectFilesToDelete2() {
+        Configuration config = new DefaultConfiguration();
+        config.initialize(); // creates the ScriptManager
+
+        List<PathWithAttributes> pathList = new ArrayList<PathWithAttributes>();
+        pathList.add(new PathWithAttributes(Paths.get("/path/1"), new DummyFileAttributes()));
+        pathList.add(new PathWithAttributes(Paths.get("/path/2"), new DummyFileAttributes()));
+        pathList.add(new PathWithAttributes(Paths.get("/path/3"), new DummyFileAttributes()));
+
+        String scriptText = "pathList.remove(1);" //
+                + "pathList;";
+        Script script = new Script("test", "javascript", scriptText);
+        ScriptCondition condition = new ScriptCondition(script, config);
+        Path base = Paths.get("baseDirectory");
+        List<PathWithAttributes> result = condition.selectFilesToDelete(base, pathList);
+        assertSame(result, pathList);
+        assertEquals(2, result.size());
+        assertEquals(Paths.get("/path/1"), result.get(0).getPath());
+        assertEquals(Paths.get("/path/3"), result.get(1).getPath());
+    }
+
+    @Test
+    public void testSelectFilesToDelete3() {
+        Configuration config = new DefaultConfiguration();
+        config.initialize(); // creates the ScriptManager
+
+        List<PathWithAttributes> pathList = new ArrayList<PathWithAttributes>();
+        pathList.add(new PathWithAttributes(Paths.get("/path/1/abc/a.txt"), new DummyFileAttributes()));
+        pathList.add(new PathWithAttributes(Paths.get("/path/2/abc/bbb.txt"), new DummyFileAttributes()));
+        pathList.add(new PathWithAttributes(Paths.get("/path/3/abc/c.txt"), new DummyFileAttributes()));
+
+        String scriptText = "" //
+                + "import java.nio.file.*;" //
+                + "def pattern = ~/(\\d*)[\\/\\\\]abc[\\/\\\\].*\\.txt/;" //
+                + "assert pattern.getClass() == java.util.regex.Pattern;" //
+                + "def copy = pathList.collect{it};"
+                + "pathList.each { pathWithAttribs -> \n" //
+                + "  def relative = basePath.relativize pathWithAttribs.path;" //
+                + "  println 'relative path: ' + relative;" //
+                + "  def str = relative.toString();"
+                + "  def m = pattern.matcher(str);" //
+                + "  if (m.find()) {" //
+                + "    def index = m.group(1) as int;" //
+                + "    println 'extracted index: ' + index;" //
+                + "    def isOdd = (index % 2) == 1;"
+                + "    println 'is odd: ' + isOdd;" //
+                + "    if (isOdd) { copy.remove pathWithAttribs}"
+                + "  }" //
+                + "}" //
+                + "println copy;"
+                + "copy;";
+        Script script = new Script("test", "groovy", scriptText);
+        ScriptCondition condition = new ScriptCondition(script, config);
+        Path base = Paths.get("/path");
+        List<PathWithAttributes> result = condition.selectFilesToDelete(base, pathList);
+        assertEquals(1, result.size());
+        assertEquals(Paths.get("/path/2/abc/bbb.txt"), result.get(0).getPath());
+    }
+
+}