Add support for getting last modified date to Resource

- Use AssetVersions.yml for jar files
- Use File#lastModified for regular files
This commit is contained in:
Aurora Lahtela 2023-01-21 15:03:29 +02:00
parent b26678b3dc
commit 0bce7880cd
9 changed files with 59 additions and 14 deletions

View File

@ -20,6 +20,7 @@ import com.djrapitops.plan.settings.config.Config;
import com.djrapitops.plan.settings.config.ConfigNode; import com.djrapitops.plan.settings.config.ConfigNode;
import com.djrapitops.plan.settings.config.ConfigReader; import com.djrapitops.plan.settings.config.ConfigReader;
import com.djrapitops.plan.storage.file.PlanFiles; import com.djrapitops.plan.storage.file.PlanFiles;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -46,7 +47,7 @@ public class AssetVersions {
} }
} }
public Optional<Long> getAssetVersion(String resource) { public Optional<Long> getAssetVersion(@Untrusted String resource) {
if (webAssetConfig == null) return Optional.empty(); if (webAssetConfig == null) return Optional.empty();
return webAssetConfig.getNode(resource.replace('.', ',')).map(ConfigNode::getLong); return webAssetConfig.getNode(resource.replace('.', ',')).map(ConfigNode::getLong);

View File

@ -62,6 +62,11 @@ public class FileResource implements Resource {
return resourceName; return resourceName;
} }
@Override
public long getLastModifiedDate() {
return file.lastModified();
}
@Override @Override
public InputStream asInputStream() throws IOException { public InputStream asInputStream() throws IOException {
return new FileInputStream(file); return new FileInputStream(file);

View File

@ -26,6 +26,7 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Scanner; import java.util.Scanner;
import java.util.function.LongSupplier;
/** /**
* {@link Resource} implementation for something that is read via InputStream. * {@link Resource} implementation for something that is read via InputStream.
@ -36,14 +37,21 @@ public class JarResource implements Resource {
private final String resourceName; private final String resourceName;
private final StreamSupplier streamSupplier; private final StreamSupplier streamSupplier;
private final LongSupplier lastModifiedSupplier;
public JarResource(String resourceName, StreamSupplier streamSupplier) { public JarResource(String resourceName, StreamSupplier streamSupplier, LongSupplier lastModifiedSupplier) {
this.resourceName = resourceName; this.resourceName = resourceName;
this.streamSupplier = streamSupplier; this.streamSupplier = streamSupplier;
this.lastModifiedSupplier = lastModifiedSupplier;
} }
public JarResource(String resourceName, StreamFunction streamFunction) { public JarResource(String resourceName, StreamFunction streamFunction, LongSupplier lastModifiedSupplier) {
this(resourceName, () -> streamFunction.get(resourceName)); this(resourceName, () -> streamFunction.get(resourceName), lastModifiedSupplier);
}
@Override
public long getLastModifiedDate() {
return lastModifiedSupplier.getAsLong();
} }
@Override @Override

View File

@ -17,11 +17,14 @@
package com.djrapitops.plan.storage.file; package com.djrapitops.plan.storage.file;
import com.djrapitops.plan.SubSystem; import com.djrapitops.plan.SubSystem;
import com.djrapitops.plan.delivery.web.AssetVersions;
import com.djrapitops.plan.exceptions.EnableException; import com.djrapitops.plan.exceptions.EnableException;
import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.CustomizedFileSettings; import com.djrapitops.plan.settings.config.paths.CustomizedFileSettings;
import com.djrapitops.plan.utilities.dev.Untrusted; import com.djrapitops.plan.utilities.dev.Untrusted;
import dagger.Lazy; import dagger.Lazy;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
@ -46,16 +49,19 @@ public class PlanFiles implements SubSystem {
private final File dataFolder; private final File dataFolder;
private final File configFile; private final File configFile;
private final Lazy<AssetVersions> assetVersions;
private final Lazy<PlanConfig> config; private final Lazy<PlanConfig> config;
@Inject @Inject
public PlanFiles( public PlanFiles(
@Named("dataFolder") File dataFolder, @Named("dataFolder") File dataFolder,
JarResource.StreamFunction getResourceStream, JarResource.StreamFunction getResourceStream,
Lazy<AssetVersions> assetVersions,
Lazy<PlanConfig> config Lazy<PlanConfig> config
) { ) {
this.dataFolder = dataFolder; this.dataFolder = dataFolder;
this.getResourceStream = getResourceStream; this.getResourceStream = getResourceStream;
this.assetVersions = assetVersions;
this.config = config; this.config = config;
this.configFile = getFileFromPluginFolder("config.yml"); this.configFile = getFileFromPluginFolder("config.yml");
} }
@ -120,7 +126,18 @@ public class PlanFiles implements SubSystem {
* @return a {@link Resource} for accessing the resource. * @return a {@link Resource} for accessing the resource.
*/ */
public Resource getResourceFromJar(@Untrusted String resourceName) { public Resource getResourceFromJar(@Untrusted String resourceName) {
return new JarResource("assets/plan/" + resourceName, getResourceStream); return new JarResource(
"assets/plan/" + resourceName,
getResourceStream,
() -> getLastModifiedForJarResource(resourceName)
);
}
@NotNull
protected Long getLastModifiedForJarResource(@Untrusted String resourceName) {
String webResourceName = StringUtils.remove(resourceName, "web/");
return assetVersions.get().getAssetVersion(webResourceName)
.orElseGet(System::currentTimeMillis);
} }
/** /**

View File

@ -42,6 +42,8 @@ public interface Resource {
@Untrusted @Untrusted
String getResourceName(); String getResourceName();
long getLastModifiedDate();
byte[] asBytes() throws IOException; byte[] asBytes() throws IOException;
/** /**

View File

@ -33,7 +33,7 @@ import java.util.function.Supplier;
*/ */
public class ResourceCache { public class ResourceCache {
private static final Cache<String, String> cache = Caffeine.newBuilder() private static final Cache<String, Resource> cache = Caffeine.newBuilder()
.expireAfterAccess(1, TimeUnit.MINUTES) .expireAfterAccess(1, TimeUnit.MINUTES)
.build(); .build();
@ -42,17 +42,17 @@ public class ResourceCache {
} }
public static Resource getOrCache(@Untrusted String resourceName, Supplier<Resource> resourceSupplier) { public static Resource getOrCache(@Untrusted String resourceName, Supplier<Resource> resourceSupplier) {
String found = cache.getIfPresent(resourceName); Resource found = cache.getIfPresent(resourceName);
if (found == null) { if (found == null) {
Resource created = resourceSupplier.get(); Resource created = resourceSupplier.get();
if (created == null) return null; if (created == null) return null;
return new StringCachingResource(created); return new StringCachingResource(created);
} }
return new StringResource(resourceName, found); return found;
} }
public static void cache(String resourceName, String got) { public static void cache(@Untrusted String resourceName, String contents, long lastModifiedDate) {
cache.put(resourceName, got); cache.put(resourceName, new StringResource(resourceName, contents, lastModifiedDate));
} }
public static void invalidateAll() { public static void invalidateAll() {

View File

@ -38,6 +38,9 @@ public class StringCachingResource implements Resource {
return implementation.getResourceName(); return implementation.getResourceName();
} }
@Override
public long getLastModifiedDate() {return implementation.getLastModifiedDate();}
@Override @Override
public InputStream asInputStream() throws IOException { public InputStream asInputStream() throws IOException {
return implementation.asInputStream(); return implementation.asInputStream();
@ -51,7 +54,7 @@ public class StringCachingResource implements Resource {
@Override @Override
public String asString() throws IOException { public String asString() throws IOException {
String got = implementation.asString(); String got = implementation.asString();
ResourceCache.cache(implementation.getResourceName(), got); ResourceCache.cache(implementation.getResourceName(), got, implementation.getLastModifiedDate());
return got; return got;
} }

View File

@ -33,10 +33,12 @@ public class StringResource implements Resource {
private final String resourceName; private final String resourceName;
private final String resource; private final String resource;
private final long lastModified;
StringResource(String resourceName, String resource) { StringResource(String resourceName, String resource, long lastModified) {
this.resourceName = resourceName; this.resourceName = resourceName;
this.resource = resource; this.resource = resource;
this.lastModified = lastModified;
} }
@Override @Override
@ -44,6 +46,11 @@ public class StringResource implements Resource {
return resourceName; return resourceName;
} }
@Override
public long getLastModifiedDate() {
return lastModified;
}
@Override @Override
public InputStream asInputStream() { public InputStream asInputStream() {
return new ByteArrayInputStream(resource.getBytes(StandardCharsets.UTF_8)); return new ByteArrayInputStream(resource.getBytes(StandardCharsets.UTF_8));

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan.storage.file;
import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.PlanSponge; import com.djrapitops.plan.PlanSponge;
import com.djrapitops.plan.delivery.web.AssetVersions;
import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.PlanConfig;
import dagger.Lazy; import dagger.Lazy;
import org.spongepowered.api.Sponge; import org.spongepowered.api.Sponge;
@ -45,9 +46,10 @@ public class SpongePlanFiles extends PlanFiles {
@Named("dataFolder") File dataFolder, @Named("dataFolder") File dataFolder,
JarResource.StreamFunction getResourceStream, JarResource.StreamFunction getResourceStream,
PlanPlugin plugin, PlanPlugin plugin,
Lazy<AssetVersions> assetVersions,
Lazy<PlanConfig> config Lazy<PlanConfig> config
) { ) {
super(dataFolder, getResourceStream, config); super(dataFolder, getResourceStream, assetVersions, config);
this.plugin = plugin; this.plugin = plugin;
} }
@ -73,7 +75,7 @@ public class SpongePlanFiles extends PlanFiles {
StringWriter writer = new StringWriter() StringWriter writer = new StringWriter()
) { ) {
reader.transferTo(writer); reader.transferTo(writer);
return new StringResource(resourceName, writer.toString()); return new StringResource(resourceName, writer.toString(), getLastModifiedForJarResource(resourceName));
} }
} }
} }