Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 37 additions & 33 deletions src/main/java/net/uiqui/embedhttp/server/DateHeader.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package net.uiqui.embedhttp.server;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Locale;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class DateHeader {
Expand All @@ -13,52 +16,53 @@ public class DateHeader {

private static final DateTimeFormatter DATE_HEADER_FORMAT = DateTimeFormatter.ofPattern(RFC_1123_DATE_TIME, Locale.ENGLISH)
.withZone(ZoneId.of(GMT));
private static final ZonedDateTime EPOCH = ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.of(GMT));

private final LastDateHolder cache = new LastDateHolder();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();

private FormatedDate lastFormattedDate = new FormatedDate(EPOCH, "");

public String getDateHeaderValue() {
var now = Now.asZonedDateTime().truncatedTo(ChronoUnit.SECONDS);
var lastFormatedDate = cache.get();

if (lastFormatedDate == null || !now.equals(lastFormatedDate.time)) {
var formattedDate = formatDate(now);
cache.set(new FormatedDate(now, formattedDate));
return formattedDate;
var currentFormattedDate = getCurrentFormattedDate();
if (now.equals(lastFormattedDate.time())) {
return currentFormattedDate.formatted();
}

return lastFormatedDate.formatted;
}

protected String formatDate(ZonedDateTime date) {
return DATE_HEADER_FORMAT.format(date);
return computeAndReturn(now);
}

private record FormatedDate(ZonedDateTime time, String formatted) {
private FormatedDate getCurrentFormattedDate() {
readLock.lock();
try {
return lastFormattedDate;
} finally {
readLock.unlock();
}
}

private static class LastDateHolder {
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
private final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();

private FormatedDate lastFormatedDate = null;

public FormatedDate get() {
readLock.lock();
try {
return lastFormatedDate;
} finally {
readLock.unlock();
private String computeAndReturn(ZonedDateTime time) {
writeLock.lock();
try {
if (lastFormattedDate.time().equals(time)) {
return lastFormattedDate.formatted();
}
}

public void set(FormatedDate formatedDate) {
writeLock.lock();
try {
lastFormatedDate = formatedDate;
} finally {
writeLock.unlock();
}
var formatted = formatDate(time);
lastFormattedDate = new FormatedDate(time, formatted);
return formatted;
} finally {
writeLock.unlock();
}
}

protected String formatDate(ZonedDateTime date) {
return DATE_HEADER_FORMAT.format(date);
}

private record FormatedDate(ZonedDateTime time, String formatted) {
}
}