LOG4J2-435 added classes and interfaces to support sorting paths before executing the 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/b7900411 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/b7900411 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/b7900411 Branch: refs/heads/master Commit: b7900411178242e14ebb2445894699890c5c0eb0 Parents: 6a1a2af Author: rpopma <[email protected]> Authored: Thu Nov 26 23:43:43 2015 +0900 Committer: rpopma <[email protected]> Committed: Thu Nov 26 23:43:43 2015 +0900 ---------------------------------------------------------------------- .../action/PathSortByModificationTime.java | 74 ++++++++++++++++ .../appender/rolling/action/PathSorter.java | 27 ++++++ .../rolling/action/PathWithAttributes.java | 52 +++++++++++ .../appender/rolling/action/SortingVisitor.java | 58 ++++++++++++ .../action/PathSortByModificationTimeTest.java | 93 ++++++++++++++++++++ .../rolling/action/SortingVisitorTest.java | 89 +++++++++++++++++++ 6 files changed, 393 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b7900411/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTime.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTime.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTime.java new file mode 100644 index 0000000..522d1c3 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTime.java @@ -0,0 +1,74 @@ +/* + * 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 org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; + +/** + * {@link PathSorter} that sorts path by their LastModified attribute. + */ +@Plugin(name = "SortByModificationTime", category = "Core", printObject = true) +public class PathSortByModificationTime implements PathSorter { + + private final boolean recentFirst; + private final int multiplier; + + /** + * Constructs a new SortByModificationTime sorter. + * + * @param recentFirst if true, most recently modified paths should come first + */ + public PathSortByModificationTime(final boolean recentFirst) { + this.recentFirst = recentFirst; + this.multiplier = recentFirst ? 1 : -1; + } + + /** + * Create a PathSorter that sorts by lastModified time. + * + * @param recentFirst if true, most recently modified paths should come first. + * @return A PathSorter. + */ + @PluginFactory + public static PathSorter createSorter( // + @PluginAttribute(value = "recentFirst", defaultBoolean = true) final boolean recentFirst) { + return new PathSortByModificationTime(recentFirst); + } + + /** + * Returns whether this sorter sorts recent files first. + * @return whether this sorter sorts recent files first + */ + public boolean isRecentFirst() { + return recentFirst; + } + + /* + * (non-Javadoc) + * + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @Override + public int compare(final PathWithAttributes path1, final PathWithAttributes path2) { + final long lastModified1 = path1.getAttributes().lastModifiedTime().toMillis(); + final long lastModified2 = path2.getAttributes().lastModifiedTime().toMillis(); + return multiplier * Long.signum(lastModified2 - lastModified1); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b7900411/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathSorter.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathSorter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathSorter.java new file mode 100644 index 0000000..2e765ab --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathSorter.java @@ -0,0 +1,27 @@ +/* + * 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.util.Comparator; + +/** + * Defines the interface of classes that can sort Paths. + */ +public interface PathSorter extends Comparator<PathWithAttributes>{ + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b7900411/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.java new file mode 100644 index 0000000..88c460a --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.java @@ -0,0 +1,52 @@ +/* + * 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.attribute.BasicFileAttributes; +import java.util.Objects; + +/** + * Tuple of a {@code Path} and {@code BasicFileAttributes}, used for sorting. + */ +public class PathWithAttributes { + + private final Path path; + private final BasicFileAttributes attributes; + + public PathWithAttributes(final Path path, final BasicFileAttributes attributes) { + this.path = Objects.requireNonNull(path, "path"); + this.attributes = Objects.requireNonNull(attributes, "attributes"); + } + + /** + * Returns the path. + * @return the path + */ + public Path getPath() { + return path; + } + + /** + * Returns the attributes. + * @return the attributes + */ + public BasicFileAttributes getAttributes() { + return attributes; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b7900411/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/SortingVisitor.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/SortingVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/SortingVisitor.java new file mode 100644 index 0000000..7bf76b6 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/SortingVisitor.java @@ -0,0 +1,58 @@ +/* + * 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.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * FileVisitor that sorts files. + */ +public class SortingVisitor extends SimpleFileVisitor<Path> { + + private final PathSorter sorter; + private final List<PathWithAttributes> collected = new ArrayList<>(); + + /** + * Constructs a new DeletingVisitor. + * + * @param basePath used to relativize paths + * @param pathFilters objects that need to confirm whether a file can be deleted + */ + public SortingVisitor(final PathSorter sorter) { + this.sorter = Objects.requireNonNull(sorter, "sorter"); + } + + @Override + public FileVisitResult visitFile(final Path path, final BasicFileAttributes attrs) throws IOException { + collected.add(new PathWithAttributes(path, attrs)); + return FileVisitResult.CONTINUE; + } + + public List<PathWithAttributes> getSortedPaths() { + Collections.sort(collected, sorter); + return collected; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b7900411/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTimeTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTimeTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTimeTest.java new file mode 100644 index 0000000..8127cac --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTimeTest.java @@ -0,0 +1,93 @@ +/* + * 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.nio.file.attribute.FileTime; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Tests the {@code PathSortByModificationTime} class. + */ +public class PathSortByModificationTimeTest { + + /** + * Test method for + * {@link org.apache.logging.log4j.core.appender.rolling.action.PathSortByModificationTime#isRecentFirst()}. + */ + @Test + public void testIsRecentFirstReturnsConstructorValue() { + assertTrue(((PathSortByModificationTime) PathSortByModificationTime.createSorter(true)).isRecentFirst()); + assertFalse(((PathSortByModificationTime) PathSortByModificationTime.createSorter(false)).isRecentFirst()); + } + + @Test + public void testCompareRecentFirst() { + PathSorter sorter = PathSortByModificationTime.createSorter(true); + Path p1 = Paths.get("aaa"); + Path p2 = Paths.get("bbb"); + DummyFileAttributes a1 = new DummyFileAttributes(); + DummyFileAttributes a2 = new DummyFileAttributes(); + a1.lastModified = FileTime.fromMillis(100); + a2.lastModified = FileTime.fromMillis(222); + + assertEquals("same path, 2nd more recent", 1, sorter.compare(path(p1, a1), path(p1, a2))); + assertEquals("path ignored, 2nd more recent", 1, sorter.compare(path(p1, a1), path(p2, a2))); + assertEquals("path ignored, 2nd more recent", 1, sorter.compare(path(p2, a1), path(p1, a2))); + + assertEquals("same path, 1st more recent", -1, sorter.compare(path(p1, a2), path(p1, a1))); + assertEquals("path ignored, 1st more recent", -1, sorter.compare(path(p1, a2), path(p2, a1))); + assertEquals("path ignored, 1st more recent", -1, sorter.compare(path(p2, a2), path(p1, a1))); + + assertEquals("same path, same time", 0, sorter.compare(path(p1, a1), path(p1, a1))); + assertEquals("path ignored, same time", 0, sorter.compare(path(p1, a1), path(p2, a1))); + assertEquals("path ignored, same time", 0, sorter.compare(path(p2, a1), path(p1, a1))); + } + + @Test + public void testCompareRecentLast() { + PathSorter sorter = PathSortByModificationTime.createSorter(false); + Path p1 = Paths.get("aaa"); + Path p2 = Paths.get("bbb"); + DummyFileAttributes a1 = new DummyFileAttributes(); + DummyFileAttributes a2 = new DummyFileAttributes(); + a1.lastModified = FileTime.fromMillis(100); + a2.lastModified = FileTime.fromMillis(222); + + assertEquals("same path, 2nd more recent", -1, sorter.compare(path(p1, a1), path(p1, a2))); + assertEquals("path ignored, 2nd more recent", -1, sorter.compare(path(p1, a1), path(p2, a2))); + assertEquals("path ignored, 2nd more recent", -1, sorter.compare(path(p2, a1), path(p1, a2))); + + assertEquals("same path, 1st more recent", 1, sorter.compare(path(p1, a2), path(p1, a1))); + assertEquals("path ignored, 1st more recent", 1, sorter.compare(path(p1, a2), path(p2, a1))); + assertEquals("path ignored, 1st more recent", 1, sorter.compare(path(p2, a2), path(p1, a1))); + + assertEquals("same path, same time", 0, sorter.compare(path(p1, a1), path(p1, a1))); + assertEquals("path ignored, same time", 0, sorter.compare(path(p1, a1), path(p2, a1))); + assertEquals("path ignored, same time", 0, sorter.compare(path(p2, a1), path(p1, a1))); + } + + private PathWithAttributes path(Path path, DummyFileAttributes attributes) { + return new PathWithAttributes(path, attributes); + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b7900411/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/SortingVisitorTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/SortingVisitorTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/SortingVisitorTest.java new file mode 100644 index 0000000..8cb2530 --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/SortingVisitorTest.java @@ -0,0 +1,89 @@ +/* + * 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.FileVisitOption; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.FileAttribute; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Tests the SortingVisitor class. + */ +public class SortingVisitorTest { + + private Path base; + private Path aaa; + private Path bbb; + private Path ccc; + + @Before + public void setUp() throws Exception { + base = Files.createTempDirectory("tempDir", new FileAttribute<?>[0]); + aaa = Files.createTempFile(base, "aaa", null, new FileAttribute<?>[0]); + Thread.sleep(1); + bbb = Files.createTempFile(base, "bbb", null, new FileAttribute<?>[0]); + Thread.sleep(1); + ccc = Files.createTempFile(base, "ccc", null, new FileAttribute<?>[0]); + } + + @After + public void tearDown() throws Exception { + Files.deleteIfExists(ccc); + Files.deleteIfExists(bbb); + Files.deleteIfExists(aaa); + Files.deleteIfExists(base); + } + + @Test + public void testRecentFirst() throws Exception { + SortingVisitor visitor = new SortingVisitor(new PathSortByModificationTime(true)); + Set<FileVisitOption> options = Collections.emptySet(); + Files.walkFileTree(base, options, 1, visitor); + + List<PathWithAttributes> found = visitor.getSortedPaths(); + assertNotNull(found); + assertEquals("file count", 3, found.size()); + assertEquals("1st: most recent", ccc, found.get(0).getPath()); + assertEquals("2nd", bbb, found.get(1).getPath()); + assertEquals("3rd: oldest", aaa, found.get(2).getPath()); + } + + @Test + public void testRecentLast() throws Exception { + SortingVisitor visitor = new SortingVisitor(new PathSortByModificationTime(false)); + Set<FileVisitOption> options = Collections.emptySet(); + Files.walkFileTree(base, options, 1, visitor); + + List<PathWithAttributes> found = visitor.getSortedPaths(); + assertNotNull(found); + assertEquals("file count", 3, found.size()); + assertEquals("1st: oldest first", aaa, found.get(0).getPath()); + assertEquals("2nd", bbb, found.get(1).getPath()); + assertEquals("3rd: most recent last", ccc, found.get(2).getPath()); + } +}
