[main] Some additions from Inceptum
This commit is contained in:
parent
57b3e2b60d
commit
58fa5c5620
|
@ -68,34 +68,6 @@ public class GsonHolder {
|
|||
* Register this in {@code SerializerHolder}
|
||||
*/
|
||||
public static void register() {
|
||||
SerializerHolder.setInstance(new Serializer() {
|
||||
@Override
|
||||
public String serialize(Object o) {
|
||||
return getGson().toJson(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T deserialize(Reader source, Type typeOfT) throws SerializeException {
|
||||
try {
|
||||
return getGson().fromJson(source, typeOfT);
|
||||
} catch (JsonIOException | JsonSyntaxException e) {
|
||||
throw new SerializeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T deserialize(String source, Type typeOfT) throws SerializeException {
|
||||
try {
|
||||
return getGson().fromJson(source, typeOfT);
|
||||
} catch (JsonIOException | JsonSyntaxException e) {
|
||||
throw new SerializeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormatMime() {
|
||||
return "application/json";
|
||||
}
|
||||
});
|
||||
Serializer.setInstance(new GsonHolderSerializer());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
package io.gitlab.jfronny.commons.serialize.gson.impl;
|
||||
|
||||
import com.google.gson.*;
|
||||
import io.gitlab.jfronny.commons.serialize.Serializer;
|
||||
import io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class GsonHolderSerializer implements Serializer {
|
||||
@Override
|
||||
public String serialize(Object object) throws IOException {
|
||||
try {
|
||||
return getGson().toJson(object);
|
||||
} catch (JsonIOException | JsonSyntaxException e) {
|
||||
throw generateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Object object, Appendable writer) throws IOException {
|
||||
try {
|
||||
getGson().toJson(object, writer);
|
||||
} catch (Exception e) {
|
||||
throw generateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T deserialize(Reader source, Class<T> typeOfT) throws IOException {
|
||||
try {
|
||||
return getGson().fromJson(source, typeOfT);
|
||||
} catch (Exception e) {
|
||||
throw generateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T deserialize(Reader source, Type typeOfT) throws IOException {
|
||||
if (typeOfT instanceof Class<?> k) {
|
||||
//noinspection unchecked
|
||||
return (T) deserialize(source, k);
|
||||
}
|
||||
try {
|
||||
return getGson().fromJson(source, typeOfT);
|
||||
} catch (Exception e) {
|
||||
throw generateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T deserialize(String source, Class<T> typeOfT) throws IOException {
|
||||
try {
|
||||
return getGson().fromJson(source, typeOfT);
|
||||
} catch (Exception e) {
|
||||
throw generateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T deserialize(String source, Type typeOfT) throws IOException {
|
||||
if (typeOfT instanceof Class<?> k) {
|
||||
//noinspection unchecked
|
||||
return (T) deserialize(source, k);
|
||||
}
|
||||
try {
|
||||
return getGson().fromJson(source, typeOfT);
|
||||
} catch (Exception e) {
|
||||
throw generateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private IOException generateException(Exception e) {
|
||||
if (e instanceof IOException io) return io;
|
||||
Throwable cause = e.getCause();
|
||||
String message = e.getMessage();
|
||||
if (cause == null) return new SerializeException(message);
|
||||
boolean lackingMessage = message == null || message.equals(cause.toString());
|
||||
if (e instanceof JsonIOException) {
|
||||
if (lackingMessage) {
|
||||
if (cause instanceof IOException io) return io;
|
||||
return new SerializeException(cause);
|
||||
}
|
||||
return new SerializeException(message, cause);
|
||||
}
|
||||
if (lackingMessage) return new SerializeException(cause);
|
||||
return new SerializeException(message, cause);
|
||||
}
|
||||
|
||||
private Gson getGson() {
|
||||
return GsonHolder.getGson();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormatMime() {
|
||||
return "application/json";
|
||||
}
|
||||
}
|
|
@ -5,6 +5,8 @@ import io.gitlab.jfronny.commons.serialize.*;
|
|||
import io.gitlab.jfronny.commons.serialize.gson.api.*;
|
||||
import org.junit.jupiter.api.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class GsonTest {
|
||||
|
@ -14,25 +16,25 @@ public class GsonTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void gsonIgnore() {
|
||||
assertEquals("null", SerializerHolder.getInstance().serialize(new ExampleTypeHidden()));
|
||||
void gsonIgnore() throws IOException {
|
||||
assertEquals("null", Serializer.getInstance().serialize(new ExampleTypeHidden()));
|
||||
assertEquals("""
|
||||
{
|
||||
"shouldShow": "Yes"
|
||||
}""", SerializerHolder.getInstance().serialize(new TransitiveHiddenType()));
|
||||
}""", Serializer.getInstance().serialize(new TransitiveHiddenType()));
|
||||
assertEquals("""
|
||||
{
|
||||
"id": "Yes",
|
||||
"shown": {
|
||||
"shouldShow": "Yes"
|
||||
}
|
||||
}""", SerializerHolder.getInstance().serialize(new ExampleType()));
|
||||
}""", Serializer.getInstance().serialize(new ExampleType()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void comparableVersionAdapter() {
|
||||
assertEquals("\"1.0.0\"", SerializerHolder.getInstance().serialize(new ComparableVersion("1.0.0")));
|
||||
assertDoesNotThrow(() -> assertEquals(new ComparableVersion("1.0.0"), SerializerHolder.getInstance().deserialize("\"1.0.0\"", ComparableVersion.class)));
|
||||
void comparableVersionAdapter() throws IOException {
|
||||
assertEquals("\"1.0.0\"", Serializer.getInstance().serialize(new ComparableVersion("1.0.0")));
|
||||
assertDoesNotThrow(() -> assertEquals(new ComparableVersion("1.0.0"), Serializer.getInstance().deserialize("\"1.0.0\"", ComparableVersion.class)));
|
||||
}
|
||||
|
||||
public static class ExampleType {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.gitlab.jfronny.commons;
|
||||
|
||||
import io.gitlab.jfronny.commons.serialize.Serializer;
|
||||
import io.gitlab.jfronny.commons.serialize.SerializerHolder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -129,8 +128,8 @@ public class HttpUtils {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Request bodySerialized(Object object) {
|
||||
Serializer serializer = SerializerHolder.getInstance();
|
||||
public Request bodySerialized(Object object) throws IOException {
|
||||
Serializer serializer = Serializer.getInstance();
|
||||
builder.header("Content-Type", serializer.getFormatMime());
|
||||
builder.method(method.name(), HttpRequest.BodyPublishers.ofString(serializer.serialize(object)));
|
||||
method = null;
|
||||
|
@ -189,7 +188,7 @@ public class HttpUtils {
|
|||
}
|
||||
|
||||
public <T> T sendSerialized(Type type) throws IOException {
|
||||
Serializer serializer = SerializerHolder.getInstance();
|
||||
Serializer serializer = Serializer.getInstance();
|
||||
InputStream in = _send(serializer.getFormatMime(), HttpResponse.BodyHandlers.ofInputStream());
|
||||
try {
|
||||
return in == null ? null : serializer.deserialize(new InputStreamReader(in), type);
|
||||
|
|
43
src/main/java/io/gitlab/jfronny/commons/cache/FileBackedOperationResultCache.java
vendored
Normal file
43
src/main/java/io/gitlab/jfronny/commons/cache/FileBackedOperationResultCache.java
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
package io.gitlab.jfronny.commons.cache;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class FileBackedOperationResultCache {
|
||||
private final ConcurrentHashMap<String, Object> container = new ConcurrentHashMap<>();
|
||||
private final Path cacheDir;
|
||||
|
||||
public FileBackedOperationResultCache(Path cacheDir) {
|
||||
this.cacheDir = cacheDir;
|
||||
}
|
||||
|
||||
public void remove(String key) throws IOException {
|
||||
container.remove(key);
|
||||
Files.delete(cacheDir.resolve(key));
|
||||
}
|
||||
|
||||
public void clear() throws IOException {
|
||||
container.clear();
|
||||
JFiles.clearDirectory(cacheDir);
|
||||
}
|
||||
|
||||
public <T, TEx extends Throwable> T get(String key, ThrowingSupplier<T, TEx> builder, Type klazz) throws IOException, TEx {
|
||||
if (!container.containsKey(key)) {
|
||||
Path cd = cacheDir.resolve(key);
|
||||
if (Files.exists(cd)) {
|
||||
T value = JFiles.readObject(cd, klazz);
|
||||
JFiles.writeObject(cd, value);
|
||||
container.put(key, value);
|
||||
}
|
||||
else container.put(key, builder.get());
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (T) container.get(key);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package io.gitlab.jfronny.commons.cache;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A linked map that discards earlier entries once a fixed size is reached
|
||||
* @param <K> the type of keys maintained by this map
|
||||
* @param <V> the type of mapped values
|
||||
*/
|
||||
public class FixedSizeMap<K, V> extends LinkedHashMap<K, V> {
|
||||
private final int maxSize;
|
||||
|
||||
public FixedSizeMap(int size) {
|
||||
super(size + 2, 1F);
|
||||
this.maxSize = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
|
||||
return size() > maxSize;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package io.gitlab.jfronny.commons.cache;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* An ordered set that discards earlier entries once a fixed size limit is reached
|
||||
* @param <E> the type of elements in this set
|
||||
*/
|
||||
public class FixedSizeSet<E> implements Set<E> {
|
||||
private final List<E> backing;
|
||||
private final int size;
|
||||
|
||||
public FixedSizeSet(int size) {
|
||||
this.backing = new LinkedList<>();
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return backing.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return backing.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return backing.contains(o);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return backing.iterator();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return backing.toArray();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public <T> T[] toArray(@NotNull T[] ts) {
|
||||
return backing.toArray(ts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
synchronized (backing) {
|
||||
if (backing.contains(e)) return false;
|
||||
if (size() >= size) backing.remove(0);
|
||||
return backing.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return backing.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(@NotNull Collection<?> collection) {
|
||||
for (Object o : Objects.requireNonNull(collection)) {
|
||||
if (!contains(o)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(@NotNull Collection<? extends E> collection) {
|
||||
synchronized (backing) {
|
||||
boolean result = false;
|
||||
for (E e : collection) {
|
||||
result |= add(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(@NotNull Collection<?> collection) {
|
||||
return backing.retainAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(@NotNull Collection<?> collection) {
|
||||
return backing.removeAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
backing.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<E> spliterator() {
|
||||
return backing.spliterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return backing.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (!(obj instanceof Set s)) return false;
|
||||
if (s.size() != this.size()) return false;
|
||||
return this.containsAll(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return backing.hashCode();
|
||||
}
|
||||
}
|
43
src/main/java/io/gitlab/jfronny/commons/cache/MemoryOperationResultCache.java
vendored
Normal file
43
src/main/java/io/gitlab/jfronny/commons/cache/MemoryOperationResultCache.java
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
package io.gitlab.jfronny.commons.cache;
|
||||
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Stores results of operations by keys
|
||||
* @param <K> The key of the operation
|
||||
* @param <V> The result of the operation
|
||||
*/
|
||||
public class MemoryOperationResultCache<K, V> {
|
||||
private final Map<K, V> container;
|
||||
|
||||
/**
|
||||
* Create a cache with a fixed size. Once it is reached, old entries will be discarded
|
||||
* @param size The size to allocate
|
||||
*/
|
||||
public MemoryOperationResultCache(int size) {
|
||||
this.container = new FixedSizeMap<>(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a cache with an unlimited size. Old entries will never be discarded. May fill up memory
|
||||
*/
|
||||
public MemoryOperationResultCache() {
|
||||
this.container = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set a value by its key. If a builder for the key is cached, the cached value will be returned instead.
|
||||
* @param key The key to cache the value for
|
||||
* @param builder A function to build a value should it not exist in the cache
|
||||
* @param <TEx> An exception the builder may throw
|
||||
* @return The result, either loaded from the cache or generated from the builder
|
||||
* @throws TEx The builder threw an exception
|
||||
*/
|
||||
public synchronized <TEx extends Throwable> V get(K key, ThrowingSupplier<V, TEx> builder) throws TEx {
|
||||
if (!container.containsKey(key)) container.put(key, builder.get());
|
||||
return container.get(key);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
package io.gitlab.jfronny.commons.io;
|
||||
|
||||
import io.gitlab.jfronny.commons.serialize.Serializer;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class JFiles {
|
||||
public static void clearDirectory(Path directory) throws IOException {
|
||||
clearDirectory(directory, p -> true);
|
||||
}
|
||||
|
||||
public static void clearDirectory(Path directory, Predicate<Path> shouldDelete) throws IOException {
|
||||
if (!Files.exists(directory)) return;
|
||||
try {
|
||||
listTo(directory, p -> {
|
||||
if (Files.isDirectory(p)) {
|
||||
try {
|
||||
if (shouldDelete.test(p))
|
||||
deleteRecursive(p, shouldDelete);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
if (shouldDelete.test(p))
|
||||
Files.delete(p);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
throw new IOException("Could not clear directory", t);
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteRecursive(Path path) throws IOException {
|
||||
deleteRecursive(path, p -> true);
|
||||
}
|
||||
|
||||
public static void deleteRecursive(Path path, Predicate<Path> shouldDelete) throws IOException {
|
||||
if (Files.isDirectory(path)) {
|
||||
Files.walkFileTree(path, new SimpleFileVisitor<>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
FileVisitResult fv = super.visitFile(file, attrs);
|
||||
if (fv != FileVisitResult.CONTINUE) return fv;
|
||||
if (shouldDelete.test(file))
|
||||
Files.delete(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
||||
FileVisitResult fv = super.postVisitDirectory(dir, exc);
|
||||
if (fv != FileVisitResult.CONTINUE) return fv;
|
||||
if (shouldDelete.test(dir) && list(dir).isEmpty()) {
|
||||
Files.delete(dir);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
}
|
||||
else Files.delete(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the source is a file, copy it to the target. If it is a directory, create the target directory if it doesn't exist and copy the source directories content there
|
||||
* @param source The path to copy from
|
||||
* @param destination The path to copy to
|
||||
* @throws IOException Something went wrong
|
||||
*/
|
||||
public static void copyContent(Path source, Path destination) throws IOException {
|
||||
copyContent(source, destination, StandardCopyOption.COPY_ATTRIBUTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the source is a file, copy it to the target. If it is a directory, create the target directory if it doesn't exist and copy the source directories content there
|
||||
* @param source The path to copy from
|
||||
* @param target The path to copy to
|
||||
* @param copyOptions Copy options to use
|
||||
* @throws IOException Something went wrong
|
||||
*/
|
||||
public static void copyContent(Path source, Path target, CopyOption... copyOptions) throws IOException {
|
||||
if (!Files.exists(target)) Files.createDirectories(target);
|
||||
boolean replaceExisting = Arrays.asList(copyOptions).contains(StandardCopyOption.REPLACE_EXISTING);
|
||||
if (Files.isDirectory(source)) {
|
||||
listTo(source, sourceResolved -> {
|
||||
Path targetResolved = target.resolve(sourceResolved.getFileName().toString());
|
||||
if (Files.exists(target)) {
|
||||
if (!replaceExisting) return;
|
||||
if (!Files.isDirectory(sourceResolved)) Files.delete(target);
|
||||
}
|
||||
copyContent(sourceResolved, targetResolved, copyOptions);
|
||||
});
|
||||
} else if (Files.exists(source)) {
|
||||
if (!Files.exists(target) || replaceExisting) Files.copy(source, target, copyOptions);
|
||||
} else throw new FileNotFoundException(source.toString());
|
||||
}
|
||||
|
||||
public static List<Path> list(Path directory) throws IOException {
|
||||
try (Stream<Path> sp = Files.list(directory)) {
|
||||
return sp.toList();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Path> list(Path directory, Predicate<Path> entryPredicate) throws IOException {
|
||||
try (Stream<Path> sp = Files.list(directory); Stream<Path> fi = sp.filter(entryPredicate)) {
|
||||
return fi.toList();
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] listNames(Path directory) throws IOException {
|
||||
try (Stream<Path> sp = Files.list(directory)) {
|
||||
return sp
|
||||
.map(p -> Files.isDirectory(p) ? p.getFileName().toString() + "/" : p.getFileName().toString())
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
}
|
||||
|
||||
public static <TEx extends Exception> void listTo(Path directory, ThrowingConsumer<Path, TEx> consumer) throws IOException, TEx {
|
||||
try (Stream<Path> sp = Files.list(directory)) {
|
||||
for (Path path : sp.toList()) consumer.accept(path);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T readObject(Path file, Type type) throws IOException {
|
||||
try (BufferedReader br = Files.newBufferedReader(file)) {
|
||||
return Serializer.getInstance().deserialize(br, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T readObject(Path file, Class<T> type) throws IOException {
|
||||
try (BufferedReader br = Files.newBufferedReader(file)) {
|
||||
return Serializer.getInstance().deserialize(br, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeObject(Path file, Object object) throws IOException {
|
||||
try (BufferedWriter bw = Files.newBufferedWriter(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
|
||||
Serializer.getInstance().serialize(object, bw);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<Path, MultiAccessFileSystem> zipFsCache = new HashMap<>();
|
||||
public static FileSystem openZipFile(Path zip, boolean create, @Nullable ClassLoader classLoader) throws IOException, URISyntaxException {
|
||||
synchronized (zipFsCache) {
|
||||
if (!zipFsCache.containsKey(zip) || zipFsCache.get(zip).isClosed()) {
|
||||
URI fileUri = zip.toUri();
|
||||
zipFsCache.put(zip, MultiAccessFileSystem.create(new URI("jar:" + fileUri.getScheme(), fileUri.getPath(), null), create ? Map.of("create", "true") : Map.of(), classLoader));
|
||||
}
|
||||
return zipFsCache.get(zip).createLens();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package io.gitlab.jfronny.commons.serialize;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
|
@ -7,12 +8,24 @@ import java.lang.reflect.Type;
|
|||
* Represents an externally defined serializer. Configure the one to use here via {@code SerializerHolder.setInstance}
|
||||
*/
|
||||
public interface Serializer {
|
||||
static Serializer getInstance() {
|
||||
return SerializerHolder.getInstance();
|
||||
}
|
||||
|
||||
static void setInstance(Serializer instance) {
|
||||
SerializerHolder.setInstance(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize an object to a string
|
||||
* @param object The object to serialize
|
||||
* @return The serialized object as a string
|
||||
*/
|
||||
String serialize(Object object);
|
||||
String serialize(Object object) throws IOException;
|
||||
|
||||
default void serialize(Object object, Appendable writer) throws IOException {
|
||||
writer.append(serialize(object));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize data from a reader to an object
|
||||
|
@ -22,7 +35,9 @@ public interface Serializer {
|
|||
* @return The deserialized object
|
||||
* @throws SerializeException if there was a problem during serialization
|
||||
*/
|
||||
<T> T deserialize(Reader source, Type typeOfT) throws SerializeException;
|
||||
default <T> T deserialize(Reader source, Class<T> typeOfT) throws IOException {
|
||||
return deserialize(source, (Type) typeOfT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize data from a reader to an object
|
||||
|
@ -32,7 +47,29 @@ public interface Serializer {
|
|||
* @return The deserialized object
|
||||
* @throws SerializeException if there was a problem during serialization
|
||||
*/
|
||||
<T> T deserialize(String source, Type typeOfT) throws SerializeException;
|
||||
<T> T deserialize(Reader source, Type typeOfT) throws IOException;
|
||||
|
||||
/**
|
||||
* Deserialize data from a reader to an object
|
||||
* @param source The source from which the object should be deserialized
|
||||
* @param typeOfT The type of the desired object
|
||||
* @param <T> The type of the desired object
|
||||
* @return The deserialized object
|
||||
* @throws SerializeException if there was a problem during serialization
|
||||
*/
|
||||
default <T> T deserialize(String source, Class<T> typeOfT) throws IOException {
|
||||
return deserialize(source, (Type) typeOfT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize data from a reader to an object
|
||||
* @param source The source from which the object should be deserialized
|
||||
* @param typeOfT The type of the desired object
|
||||
* @param <T> The type of the desired object
|
||||
* @return The deserialized object
|
||||
* @throws SerializeException if there was a problem during serialization
|
||||
*/
|
||||
<T> T deserialize(String source, Type typeOfT) throws IOException;
|
||||
|
||||
/**
|
||||
* The MIME type for serialized data, for example application/json
|
||||
|
@ -43,7 +80,7 @@ public interface Serializer {
|
|||
/**
|
||||
* An exception to be thrown when deserialization fails
|
||||
*/
|
||||
class SerializeException extends Exception {
|
||||
class SerializeException extends IOException {
|
||||
public SerializeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.Objects;
|
|||
/**
|
||||
* Holds a serializer for use elsewhere
|
||||
*/
|
||||
public class SerializerHolder {
|
||||
class SerializerHolder {
|
||||
private static Serializer instance;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue