Various small fixes

This commit is contained in:
Christopher Schnick
2022-12-23 10:29:08 +01:00
parent 71b5d2d716
commit 9a2a1a8745
18 changed files with 415 additions and 137 deletions
@@ -1,49 +1,111 @@
package io.xpipe.core.charsetter;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import io.xpipe.core.util.Identifiers;
import lombok.Value;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Stream;
@Value
public class StreamCharset {
public static final StreamCharset UTF8 = new StreamCharset(StandardCharsets.UTF_8, null);
public static final StreamCharset UTF8_BOM =
new StreamCharset(StandardCharsets.UTF_8, new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
public static final StreamCharset UTF16_BE = new StreamCharset(StandardCharsets.UTF_16BE, null);
public static final StreamCharset UTF16_BE_BOM =
new StreamCharset(StandardCharsets.UTF_16BE, new byte[] {(byte) 0xFE, (byte) 0xFF});
public static final StreamCharset UTF16_LE = new StreamCharset(StandardCharsets.UTF_16LE, null);
public static final StreamCharset UTF16_LE_BOM =
new StreamCharset(StandardCharsets.UTF_16LE, new byte[] {(byte) 0xFF, (byte) 0xFE});
public static final StreamCharset UTF8 =
new StreamCharset(StandardCharsets.UTF_8, null, Identifiers.get("utf", "8"));
public static final StreamCharset UTF32_LE = new StreamCharset(Charset.forName("utf-32le"), null);
public static final StreamCharset UTF32_LE_BOM =
new StreamCharset(Charset.forName("utf-32le"), new byte[] {0x00, 0x00, (byte) 0xFE, (byte) 0xFF});
public static final StreamCharset UTF32_BE = new StreamCharset(Charset.forName("utf-32be"), null);
public static final StreamCharset UTF32_BE_BOM =
new StreamCharset(Charset.forName("utf-32be"), new byte[] {(byte) 0xFF, (byte) 0xFE, 0x00, 0x00, });
public static final StreamCharset UTF8_BOM = new StreamCharset(
StandardCharsets.UTF_8,
new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF},
Identifiers.get("utf", "8", "bom"));
// ======
// UTF-16
// ======
public static final StreamCharset UTF16_BE =
new StreamCharset(StandardCharsets.UTF_16BE, null, Identifiers.get("utf", "16", "be"));
public static final StreamCharset UTF16_BE_BOM = new StreamCharset(
StandardCharsets.UTF_16BE,
new byte[] {(byte) 0xFE, (byte) 0xFF},
Identifiers.get("utf", "16", "be", "bom"));
public static final StreamCharset UTF16_LE =
new StreamCharset(StandardCharsets.UTF_16LE, null, Identifiers.get("utf", "16", "le"));
public static final StreamCharset UTF16_LE_BOM = new StreamCharset(
StandardCharsets.UTF_16LE,
new byte[] {(byte) 0xFF, (byte) 0xFE},
Identifiers.get("utf", "16", "le", "bom"));
public static final StreamCharset UTF16 =
new StreamCharset(StandardCharsets.UTF_16, null, Identifiers.get("utf", "16"));
public static final StreamCharset UTF16_BOM = new StreamCharset(
StandardCharsets.UTF_16,
ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN)
? UTF16_BE_BOM.getByteOrderMark()
: UTF16_LE_BOM.getByteOrderMark(),
Identifiers.get("utf", "16", "bom"));
// ======
// UTF-32
// ======
public static final StreamCharset UTF32_LE =
new StreamCharset(Charset.forName("utf-32le"), null, Identifiers.get("utf", "32", "le"));
public static final StreamCharset UTF32_LE_BOM = new StreamCharset(
Charset.forName("utf-32le"),
new byte[] {0x00, 0x00, (byte) 0xFE, (byte) 0xFF},
Identifiers.get("utf", "32", "le", "bom"));
public static final StreamCharset UTF32_BE =
new StreamCharset(Charset.forName("utf-32be"), null, Identifiers.get("utf", "32", "be"));
public static final StreamCharset UTF32_BE_BOM = new StreamCharset(
Charset.forName("utf-32be"),
new byte[] {
(byte) 0xFF, (byte) 0xFE, 0x00, 0x00,
},
Identifiers.get("utf", "32", "be", "bom"));
public static final List<StreamCharset> COMMON = List.of(
UTF8,
UTF8_BOM,
UTF16_BE,
UTF16_BE_BOM,
UTF16_LE,
UTF16_LE_BOM,
new StreamCharset(StandardCharsets.US_ASCII, null),
new StreamCharset(StandardCharsets.ISO_8859_1, null),
new StreamCharset(Charset.forName("Windows-1251"), null),
new StreamCharset(Charset.forName("Windows-1252"), null));
private static final List<StreamCharset> RARE_KNOWN = List.of(UTF32_LE, UTF32_LE_BOM, UTF32_BE, UTF32_BE_BOM);
UTF16,
UTF16_BOM,
new StreamCharset(
StandardCharsets.US_ASCII,
null,
Identifiers.join(Identifiers.get("ascii"), Identifiers.get("us", "ascii"))),
new StreamCharset(
StandardCharsets.ISO_8859_1,
null,
Identifiers.join(
Identifiers.get("iso", "8859"),
Identifiers.get("iso", "8859", "1"),
Identifiers.get("8859"),
Identifiers.get("8859", "1"))),
new StreamCharset(
Charset.forName("Windows-1251"),
null,
Identifiers.join(Identifiers.get("windows", "1251"), Identifiers.get("1251"))),
new StreamCharset(
Charset.forName("Windows-1252"),
null,
Identifiers.join(Identifiers.get("windows", "1252"), Identifiers.get("1252"))));
private static final List<StreamCharset> RARE_NAMED =
List.of(UTF16_LE, UTF16_LE_BOM, UTF16_BE, UTF16_BE_BOM, UTF32_LE, UTF32_LE_BOM, UTF32_BE, UTF32_BE_BOM);
public static final List<StreamCharset> RARE = Stream.concat(
RARE_KNOWN.stream(),
RARE_NAMED.stream(),
Charset.availableCharsets().values().stream()
.filter(charset -> !charset.equals(StandardCharsets.UTF_16)
&& !charset.equals(Charset.forName("utf-32"))
@@ -52,31 +114,59 @@ public class StreamCharset {
&& !charset.displayName().endsWith("-BOM")
&& COMMON.stream()
.noneMatch(c -> c.getCharset().equals(charset))
&& RARE_KNOWN.stream()
&& RARE_NAMED.stream()
.noneMatch(c -> c.getCharset().equals(charset)))
.map(charset -> new StreamCharset(charset, null)))
.map(charset -> new StreamCharset(
charset,
null,
Identifiers.get(charset.name().split("-")))))
.toList();
public static final List<StreamCharset> ALL = Stream.concat(COMMON.stream(), RARE.stream()).toList();
Charset charset;
byte[] byteOrderMark;
List<String> names;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof StreamCharset that)) {
return false;
}
return charset.equals(that.charset) && Arrays.equals(byteOrderMark, that.byteOrderMark);
}
@Override
public int hashCode() {
int result = Objects.hash(charset);
result = 31 * result + Arrays.hashCode(byteOrderMark);
return result;
}
public static StreamCharset get(Charset charset, boolean byteOrderMark) {
return Stream.concat(COMMON.stream(), RARE.stream())
return ALL.stream()
.filter(streamCharset ->
streamCharset.getCharset().equals(charset) && streamCharset.hasByteOrderMark() == byteOrderMark)
.findFirst()
.orElseThrow();
}
@JsonCreator
public static StreamCharset get(String s) {
var byteOrderMark = s.endsWith("-bom");
var charset = Charset.forName(s.substring(0, s.length() - (byteOrderMark ? 4 : 0)));
return StreamCharset.get(charset, byteOrderMark);
var found = ALL.stream().filter(streamCharset -> streamCharset.getNames().contains(s.toLowerCase(Locale.ROOT))).findFirst();
if (found.isEmpty()) {
throw new IllegalArgumentException("Unknown charset name: " + s);
}
return found.get();
}
@JsonValue
public String toString() {
return getCharset().name().toLowerCase(Locale.ROOT) + (hasByteOrderMark() ? "-bom" : "");
return getNames().get(0);
}
public boolean hasByteOrderMark() {
@@ -0,0 +1,61 @@
package io.xpipe.core.impl;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.core.store.DataFlow;
import io.xpipe.core.store.StreamDataStore;
import io.xpipe.core.util.DataStateProvider;
import io.xpipe.core.util.JacksonizedValue;
import lombok.Getter;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.util.Optional;
import java.util.UUID;
@JsonTypeName("internalStream")
@SuperBuilder
@Jacksonized
@Getter
public class InternalStreamStore extends JacksonizedValue implements StreamDataStore {
private final UUID uuid;
public InternalStreamStore() {
this.uuid = UUID.randomUUID();
}
@Override
public DataFlow getFlow() {
return DataFlow.INPUT_OUTPUT;
}
@Override
public Optional<String> determineDefaultName() {
return Optional.of(uuid.toString());
}
private Path getFile() {
return DataStateProvider.get().getInternalStreamStore(uuid);
}
@Override
public Optional<Instant> determineLastModified() throws IOException {
return Optional.of(Files.getLastModifiedTime(getFile()).toInstant());
}
@Override
public InputStream openInput() throws Exception {
return Files.newInputStream(getFile());
}
@Override
public OutputStream openOutput() throws Exception {
return Files.newOutputStream(getFile());
}
}
@@ -5,6 +5,7 @@ import io.xpipe.core.impl.StdinDataStore;
import io.xpipe.core.impl.StdoutDataStore;
import io.xpipe.core.source.DataSource;
import java.io.IOException;
import java.time.Instant;
import java.util.Optional;
@@ -101,7 +102,7 @@ public interface DataStore {
/**
* Determines the last modified of this data store if this data store supports it.
*/
default Optional<Instant> determineLastModified() {
default Optional<Instant> determineLastModified() throws IOException {
return Optional.empty();
}
}
@@ -2,7 +2,9 @@ package io.xpipe.core.util;
import io.xpipe.core.store.DataStore;
import java.nio.file.Path;
import java.util.ServiceLoader;
import java.util.UUID;
import java.util.function.Supplier;
public abstract class DataStateProvider {
@@ -22,4 +24,6 @@ public abstract class DataStateProvider {
public abstract void putState(DataStore store, String key, Object value);
public abstract <T> T getState(DataStore store, String key, Class<T> c, Supplier<T> def);
public abstract Path getInternalStreamStore(UUID id);
}
@@ -0,0 +1,25 @@
package io.xpipe.core.util;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class Identifiers {
@SafeVarargs
public static List<String> join(List<String>... s) {
return Arrays.stream(s).flatMap(Collection::stream).toList();
}
public static List<String> get(String... s) {
return nameAlternatives(Arrays.asList(s));
}
private static List<String> nameAlternatives(List<String> split) {
return List.of(
String.join("", split),
String.join(" ", split),
String.join("_", split),
String.join("-", split));
}
}