diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/RolloverFileOutputStream.java b/jetty-util/src/main/java/org/eclipse/jetty/util/RolloverFileOutputStream.java index d83385de389..8f8314062ad 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/RolloverFileOutputStream.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/RolloverFileOutputStream.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.Locale; import java.util.TimeZone; @@ -117,9 +118,9 @@ public class RolloverFileOutputStream extends FilterOutputStream TimeZone zone) throws IOException { - this(filename,append,retainDays,zone,null,null); + this(filename,append,retainDays,zone,null,null,ZonedDateTime.now(zone.toZoneId())); } - + /* ------------------------------------------------------------ */ /** * @param filename The filename must include the string "yyyy_mm_dd", @@ -138,20 +139,33 @@ public class RolloverFileOutputStream extends FilterOutputStream String dateFormat, String backupFormat) throws IOException + { + this(filename,append,retainDays,zone,dateFormat,backupFormat,ZonedDateTime.now(zone.toZoneId())); + } + + + RolloverFileOutputStream(String filename, + boolean append, + int retainDays, + TimeZone zone, + String dateFormat, + String backupFormat, + ZonedDateTime now) + throws IOException { super(null); if (dateFormat==null) dateFormat=ROLLOVER_FILE_DATE_FORMAT; _fileDateFormat = new SimpleDateFormat(dateFormat); - + if (backupFormat==null) backupFormat=ROLLOVER_FILE_BACKUP_FORMAT; _fileBackupFormat = new SimpleDateFormat(backupFormat); - + _fileBackupFormat.setTimeZone(zone); _fileDateFormat.setTimeZone(zone); - + if (filename!=null) { filename=filename.trim(); @@ -171,7 +185,6 @@ public class RolloverFileOutputStream extends FilterOutputStream __rollover=new Timer(RolloverFileOutputStream.class.getName(),true); // Calculate Today's Midnight, based on Configured TimeZone (will be in past, even if by a few milliseconds) - ZonedDateTime now = ZonedDateTime.now(zone.toZoneId()); setFile(now); // This will schedule the rollover event to the next midnight scheduleNextRollover(now); @@ -187,7 +200,7 @@ public class RolloverFileOutputStream extends FilterOutputStream */ public static ZonedDateTime toMidnight(ZonedDateTime now) { - return now.toLocalDate().atStartOfDay(now.getZone()); + return now.toLocalDate().atStartOfDay(now.getZone()).plus(1, ChronoUnit.DAYS); } /* ------------------------------------------------------------ */ @@ -223,7 +236,7 @@ public class RolloverFileOutputStream extends FilterOutputStream } /* ------------------------------------------------------------ */ - private synchronized void setFile(ZonedDateTime now) + synchronized void setFile(ZonedDateTime now) throws IOException { // Check directory @@ -264,12 +277,12 @@ public class RolloverFileOutputStream extends FilterOutputStream } /* ------------------------------------------------------------ */ - private void removeOldFiles(ZonedDateTime now) + void removeOldFiles(ZonedDateTime now) { if (_retainDays>0) { // Establish expiration time, based on configured TimeZone - long expired = now.toInstant().toEpochMilli(); + long expired = now.minus(_retainDays, ChronoUnit.DAYS).toInstant().toEpochMilli(); File file= new File(_filename); File dir = new File(file.getParent()); diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java index 0cc9faeb358..6d2d487021e 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/RolloverFileOutputStreamTest.java @@ -21,13 +21,23 @@ package org.eclipse.jetty.util; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAccessor; +import java.util.Arrays; import java.util.TimeZone; +import org.eclipse.jetty.toolchain.test.FS; +import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.util.resource.ResourceTest; +import org.hamcrest.Matchers; import org.junit.Test; public class RolloverFileOutputStreamTest @@ -93,7 +103,7 @@ public class RolloverFileOutputStreamTest public void testMidnightRolloverCalc_PST_DST_Start() { ZoneId zone = toZoneId("PST"); - ZonedDateTime initialDate = toDateTime("2016.03.11-01:23:45.0 PM PST", zone); + ZonedDateTime initialDate = toDateTime("2016.03.10-01:23:45.0 PM PST", zone); ZonedDateTime midnight = RolloverFileOutputStream.toMidnight(initialDate); assertThat("Midnight", toString(midnight), is("2016.03.11-12:00:00.0 AM PST")); @@ -113,7 +123,7 @@ public class RolloverFileOutputStreamTest public void testMidnightRolloverCalc_PST_DST_End() { ZoneId zone = toZoneId("PST"); - ZonedDateTime initialDate = toDateTime("2016.11.04-11:22:33.0 AM PDT", zone); + ZonedDateTime initialDate = toDateTime("2016.11.03-11:22:33.0 AM PDT", zone); ZonedDateTime midnight = RolloverFileOutputStream.toMidnight(initialDate); assertThat("Midnight", toString(midnight), is("2016.11.04-12:00:00.0 AM PDT")); @@ -133,7 +143,7 @@ public class RolloverFileOutputStreamTest public void testMidnightRolloverCalc_Sydney_DST_Start() { ZoneId zone = toZoneId("Australia/Sydney"); - ZonedDateTime initialDate = toDateTime("2016.10.01-01:23:45.0 PM AEST", zone); + ZonedDateTime initialDate = toDateTime("2016.09.31-01:23:45.0 PM AEST", zone); ZonedDateTime midnight = RolloverFileOutputStream.toMidnight(initialDate); assertThat("Midnight", toString(midnight), is("2016.10.01-12:00:00.0 AM AEST")); @@ -153,7 +163,7 @@ public class RolloverFileOutputStreamTest public void testMidnightRolloverCalc_Sydney_DST_End() { ZoneId zone = toZoneId("Australia/Sydney"); - ZonedDateTime initialDate = toDateTime("2016.04.02-11:22:33.0 AM AEDT", zone); + ZonedDateTime initialDate = toDateTime("2016.04.01-11:22:33.0 AM AEDT", zone); ZonedDateTime midnight = RolloverFileOutputStream.toMidnight(initialDate); assertThat("Midnight", toString(midnight), is("2016.04.02-12:00:00.0 AM AEDT")); @@ -168,4 +178,73 @@ public class RolloverFileOutputStreamTest assertSequence(midnight, expected); } + + @Test + public void testFilehandling() throws Exception + { + File testDir = MavenTestingUtils.getTargetTestingDir(ResourceTest.class.getName()); + Path testPath = testDir.toPath(); + FS.ensureEmpty(testDir); + + ZoneId zone = toZoneId("Australia/Sydney"); + ZonedDateTime now = toDateTime("2016.04.10-08:30:12.3 AM AEDT", zone); + + File template = new File(testDir,"test-rofos-yyyy_mm_dd.log"); + + try (RolloverFileOutputStream rofos = + new RolloverFileOutputStream(template.getAbsolutePath(),false,3,TimeZone.getTimeZone(zone),null,null,now)) + { + String[] ls = testDir.list(); + assertThat(ls.length,is(1)); + assertThat(ls[0],is("test-rofos-2016_04_10.log")); + Files.setLastModifiedTime(testPath.resolve("test-rofos-2016_04_10.log"),FileTime.from(now.toInstant())); + + ZonedDateTime time = now.minus(1,ChronoUnit.DAYS); + for (int i=10;i-->5;) + { + String file = "test-rofos-2016_04_0"+i+".log"; + Path path = testPath.resolve(file); + FS.touch(path); + Files.setLastModifiedTime(path,FileTime.from(time.toInstant())); + time = time.minus(1,ChronoUnit.DAYS); + } + for (int i=10;i-->5;) + { + String file = "unrelated-"+i; + Path path = testPath.resolve(file); + FS.touch(path); + Files.setLastModifiedTime(path,FileTime.from(time.toInstant())); + time = time.minus(1,ChronoUnit.DAYS); + } + + ls = testDir.list(); + assertThat(ls.length,is(11)); + assertThat(Arrays.asList(ls),Matchers.containsInAnyOrder( + "test-rofos-2016_04_05.log", + "test-rofos-2016_04_06.log", + "test-rofos-2016_04_07.log", + "test-rofos-2016_04_08.log", + "test-rofos-2016_04_09.log", + "test-rofos-2016_04_10.log", + "unrelated-9", + "unrelated-8", + "unrelated-7", + "unrelated-6", + "unrelated-5" + )); + + rofos.removeOldFiles(now); + ls = testDir.list(); + assertThat(ls.length,is(8)); + assertThat(Arrays.asList(ls),Matchers.containsInAnyOrder( + "test-rofos-2016_04_08.log", + "test-rofos-2016_04_09.log", + "test-rofos-2016_04_10.log", + "unrelated-9", + "unrelated-8", + "unrelated-7", + "unrelated-6", + "unrelated-5")); + } + } }