mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-04-25 17:07:26 -04:00
Rework
This commit is contained in:
@@ -33,8 +33,10 @@ public abstract class ArrayNode extends DataStructureNode {
|
||||
}
|
||||
|
||||
var toReturn = getNodes().equals(that.getNodes()) && Objects.equals(getMetaAttributes(), that.getMetaAttributes());
|
||||
|
||||
// Useful for debugging
|
||||
if (toReturn == false) {
|
||||
throw new AssertionError();
|
||||
return false;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@ import lombok.NonNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class SimpleImmutableValueNode extends ValueNode {
|
||||
public class SimpleValueNode extends ValueNode {
|
||||
|
||||
private final byte @NonNull [] data;
|
||||
|
||||
SimpleImmutableValueNode(byte @NonNull [] data) {
|
||||
SimpleValueNode(byte @NonNull [] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@@ -18,10 +18,6 @@ public class SimpleImmutableValueNode extends ValueNode {
|
||||
|
||||
@Override
|
||||
public final String asString() {
|
||||
if (getRawData().length == 0 && !hasMetaAttribute(IS_TEXT)) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
return new String(getRawData(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@@ -59,11 +59,18 @@ public abstract class TupleNode extends DataStructureNode {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof TupleNode that)) return false;
|
||||
var toReturn = getKeyNames().equals(that.getKeyNames()) && getNodes().equals(that.getNodes()) && Objects.equals(getMetaAttributes(), that.getMetaAttributes());
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof TupleNode that)) {
|
||||
return false;
|
||||
}
|
||||
var toReturn = getKeyNames().equals(that.getKeyNames()) && getNodes().equals(that.getNodes()) &&
|
||||
Objects.equals(getMetaAttributes(), that.getMetaAttributes());
|
||||
|
||||
// Useful for debugging
|
||||
if (toReturn == false) {
|
||||
throw new AssertionError();
|
||||
return false;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
@@ -93,7 +100,8 @@ public abstract class TupleNode extends DataStructureNode {
|
||||
boolean hasKeys = entries.stream().anyMatch(kv -> kv.key() != null);
|
||||
return hasKeys ? TupleNode.of(
|
||||
entries.stream().map(KeyValue::key).toList(),
|
||||
entries.stream().map(KeyValue::value).toList()) :
|
||||
entries.stream().map(KeyValue::value).toList()
|
||||
) :
|
||||
TupleNode.of(entries.stream().map(KeyValue::value).toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,12 @@ public abstract class ValueNode extends DataStructureNode {
|
||||
return false;
|
||||
}
|
||||
var toReturn = Arrays.equals(getRawData(), that.getRawData()) && Objects.equals(getMetaAttributes(), that.getMetaAttributes());
|
||||
|
||||
// Useful for debugging
|
||||
if (toReturn == false) {
|
||||
throw new AssertionError();
|
||||
return false;
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -36,7 +39,7 @@ public abstract class ValueNode extends DataStructureNode {
|
||||
}
|
||||
|
||||
public static ValueNode nullValue() {
|
||||
return new SimpleImmutableValueNode(new byte[0]).tag(IS_NULL).asValue();
|
||||
return new SimpleValueNode(new byte[0]).tag(IS_NULL).asValue();
|
||||
}
|
||||
|
||||
public static ValueNode of(byte[] data) {
|
||||
@@ -44,7 +47,7 @@ public abstract class ValueNode extends DataStructureNode {
|
||||
return nullValue();
|
||||
}
|
||||
|
||||
return new SimpleImmutableValueNode(data);
|
||||
return new SimpleValueNode(data);
|
||||
}
|
||||
|
||||
public static ValueNode ofBytes(byte[] data) {
|
||||
|
||||
@@ -11,16 +11,19 @@ import java.util.List;
|
||||
|
||||
public abstract class BatchTableWriteConnection implements TableWriteConnection {
|
||||
|
||||
public static final int BATCH_SIZE = 2000;
|
||||
public static final int DEFAULT_BATCH_SIZE = 2000;
|
||||
|
||||
protected final int batchSize = DEFAULT_BATCH_SIZE;
|
||||
private final List<DataStructureNode> batch = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public final DataStructureNodeAcceptor<TupleNode> writeLinesAcceptor() {
|
||||
return node -> {
|
||||
if (batch.size() < BATCH_SIZE) {
|
||||
if (batch.size() < batchSize) {
|
||||
batch.add(node);
|
||||
return true;
|
||||
if (batch.size() < batchSize) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var array = ArrayNode.of(batch);
|
||||
@@ -32,12 +35,15 @@ public abstract class BatchTableWriteConnection implements TableWriteConnection
|
||||
|
||||
@Override
|
||||
public final void close() throws Exception {
|
||||
if (batch.size() > 0) {
|
||||
var array = ArrayNode.of(batch);
|
||||
var returned = writeBatchLinesAcceptor().accept(array);
|
||||
batch.clear();
|
||||
try {
|
||||
if (batch.size() > 0) {
|
||||
var array = ArrayNode.of(batch);
|
||||
var returned = writeBatchLinesAcceptor().accept(array);
|
||||
batch.clear();
|
||||
}
|
||||
} finally {
|
||||
onClose();
|
||||
}
|
||||
onClose();
|
||||
}
|
||||
|
||||
protected abstract void onClose() throws Exception;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.xpipe.core.impl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import io.xpipe.core.data.node.DataStructureNodeAcceptor;
|
||||
@@ -10,7 +9,7 @@ import io.xpipe.core.data.typed.TypedDataStreamParser;
|
||||
import io.xpipe.core.data.typed.TypedDataStructureNodeReader;
|
||||
import io.xpipe.core.source.TableReadConnection;
|
||||
import io.xpipe.core.store.StreamDataStore;
|
||||
import io.xpipe.core.util.JacksonHelper;
|
||||
import io.xpipe.core.util.JacksonMapper;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
@@ -35,7 +34,7 @@ public class XpbtReadConnection implements TableReadConnection {
|
||||
|
||||
var headerLength = header.getBytes(StandardCharsets.UTF_8).length;
|
||||
this.inputStream.skip(headerLength + 1);
|
||||
List<String> names = JacksonHelper.newMapper()
|
||||
List<String> names = JacksonMapper.newMapper()
|
||||
.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE)
|
||||
.readerFor(new TypeReference<List<String>>() {
|
||||
}).readValue(header);
|
||||
|
||||
@@ -9,7 +9,7 @@ import io.xpipe.core.data.type.TupleType;
|
||||
import io.xpipe.core.data.typed.TypedDataStreamWriter;
|
||||
import io.xpipe.core.source.TableWriteConnection;
|
||||
import io.xpipe.core.store.StreamDataStore;
|
||||
import io.xpipe.core.util.JacksonHelper;
|
||||
import io.xpipe.core.util.JacksonMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -58,7 +58,7 @@ public class XpbtWriteConnection implements TableWriteConnection {
|
||||
try (JsonGenerator g = f.createGenerator(writer)
|
||||
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
|
||||
.setPrettyPrinter(new DefaultPrettyPrinter())) {
|
||||
JacksonHelper.newMapper().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
|
||||
JacksonMapper.newMapper().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
|
||||
.writeValue(g, tupleNode.getKeyNames());
|
||||
writer.append("\n");
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import io.xpipe.core.impl.TextSource;
|
||||
import io.xpipe.core.impl.XpbtSource;
|
||||
import io.xpipe.core.store.DataFlow;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import io.xpipe.core.util.JacksonHelper;
|
||||
import io.xpipe.core.util.JacksonMapper;
|
||||
import io.xpipe.core.util.JacksonizedValue;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
@@ -25,7 +26,7 @@ import java.util.Optional;
|
||||
use = JsonTypeInfo.Id.NAME,
|
||||
property = "type"
|
||||
)
|
||||
public abstract class DataSource<DS extends DataStore> {
|
||||
public abstract class DataSource<DS extends DataStore> extends JacksonizedValue {
|
||||
|
||||
|
||||
public static DataSource<?> createInternalDataSource(DataSourceType t, DataStore store) {
|
||||
@@ -48,7 +49,7 @@ public abstract class DataSource<DS extends DataStore> {
|
||||
|
||||
|
||||
public void test() throws Exception {
|
||||
store.test();
|
||||
store.validate();
|
||||
}
|
||||
|
||||
public void validate() throws Exception {
|
||||
@@ -56,7 +57,7 @@ public abstract class DataSource<DS extends DataStore> {
|
||||
throw new IllegalStateException("Store cannot be null");
|
||||
}
|
||||
|
||||
store.validate();
|
||||
store.checkComplete();
|
||||
}
|
||||
|
||||
public WriteMode[] getAvailableWriteModes() {
|
||||
@@ -79,38 +80,12 @@ public abstract class DataSource<DS extends DataStore> {
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends DataSource<DS>> T copy() {
|
||||
var mapper = JacksonHelper.newMapper();
|
||||
var mapper = JacksonMapper.newMapper();
|
||||
TokenBuffer tb = new TokenBuffer(mapper, false);
|
||||
mapper.writeValue(tb, this);
|
||||
return (T) mapper.readValue(tb.asParser(), getClass());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public final String toString() {
|
||||
var tree = JacksonHelper.newMapper().valueToTree(this);
|
||||
return tree.toPrettyString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var tree = JacksonHelper.newMapper().valueToTree(this);
|
||||
var otherTree = JacksonHelper.newMapper().valueToTree(o);
|
||||
return tree.equals(otherTree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
var tree = JacksonHelper.newMapper().valueToTree(this);
|
||||
return tree.hashCode();
|
||||
}
|
||||
|
||||
public DataSource<DS> withStore(DS store) {
|
||||
var c = copy();
|
||||
c.store = store;
|
||||
|
||||
@@ -21,6 +21,12 @@ public abstract class TableDataSource<DS extends DataStore> extends DataSource<D
|
||||
}
|
||||
|
||||
public final TableReadConnection openReadConnection() throws Exception {
|
||||
try {
|
||||
validate();
|
||||
} catch (Exception e) {
|
||||
return TableReadConnection.empty();
|
||||
}
|
||||
|
||||
var con = newReadConnection();
|
||||
con.init();
|
||||
return con;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.xpipe.core.store;
|
||||
|
||||
public abstract class CollectionEntryDataStore implements StreamDataStore, FilenameStore {
|
||||
public abstract class CollectionEntryDataStore implements FilenameStore, StreamDataStore {
|
||||
|
||||
private final boolean directory;
|
||||
private final String name;
|
||||
|
||||
@@ -56,10 +56,10 @@ public interface DataStore {
|
||||
*
|
||||
* @throws Exception if any part of the validation went wrong
|
||||
*/
|
||||
default void test() throws Exception {
|
||||
default void validate() throws Exception {
|
||||
}
|
||||
|
||||
default void validate() throws Exception {
|
||||
default void checkComplete() throws Exception {
|
||||
}
|
||||
|
||||
default boolean delete() throws Exception {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import io.xpipe.core.util.JacksonizedValue;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import java.io.InputStream;
|
||||
@@ -12,11 +13,11 @@ import java.nio.file.Path;
|
||||
/**
|
||||
* Represents a file located on a certain machine.
|
||||
*/
|
||||
@Value
|
||||
@JsonTypeName("file")
|
||||
@Builder
|
||||
@SuperBuilder
|
||||
@Jacksonized
|
||||
public class FileStore implements StreamDataStore, FilenameStore {
|
||||
@Getter
|
||||
public class FileStore extends JacksonizedValue implements FilenameStore, StreamDataStore {
|
||||
|
||||
public static FileStore local(Path p) {
|
||||
return new FileStore(new LocalStore(), p.toString());
|
||||
@@ -32,8 +33,13 @@ public class FileStore implements StreamDataStore, FilenameStore {
|
||||
MachineFileStore machine;
|
||||
String file;
|
||||
|
||||
public FileStore(MachineFileStore machine, String file) {
|
||||
this.machine = machine;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws Exception {
|
||||
public void checkComplete() throws Exception {
|
||||
if (machine == null) {
|
||||
throw new IllegalStateException("Machine is missing");
|
||||
}
|
||||
|
||||
@@ -2,25 +2,24 @@ package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import lombok.Value;
|
||||
import lombok.experimental.NonFinal;
|
||||
import io.xpipe.core.util.JacksonizedValue;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* A store whose contents are stored in memory.
|
||||
*/
|
||||
@Value
|
||||
@JsonTypeName("inMemory")
|
||||
public class InMemoryStore implements StreamDataStore {
|
||||
@SuperBuilder
|
||||
@Jacksonized
|
||||
@Getter
|
||||
public class InMemoryStore extends JacksonizedValue implements StreamDataStore {
|
||||
|
||||
@NonFinal
|
||||
byte[] value;
|
||||
private byte[] value;
|
||||
|
||||
public InMemoryStore() {
|
||||
this.value = new byte[0];
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public InMemoryStore(byte[] value) {
|
||||
@@ -47,8 +46,4 @@ public class InMemoryStore implements StreamDataStore {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String(value, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@ package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.xpipe.core.charsetter.NewLine;
|
||||
import io.xpipe.core.util.JacksonizedValue;
|
||||
import io.xpipe.core.util.SecretValue;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -16,9 +15,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@JsonTypeName("local")
|
||||
@Value
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class LocalStore extends StandardShellStore implements MachineFileStore {
|
||||
public class LocalStore extends JacksonizedValue implements MachineFileStore, StandardShellStore {
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
|
||||
@@ -7,11 +7,6 @@ import java.io.OutputStream;
|
||||
|
||||
public interface MachineFileStore extends DataStore {
|
||||
|
||||
default boolean isLocal(){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
InputStream openInput(String file) throws Exception;
|
||||
|
||||
OutputStream openOutput(String file) throws Exception;
|
||||
|
||||
@@ -23,7 +23,7 @@ public final class NamedStore implements DataStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
public void validate() throws Exception {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ public abstract class ProcessControl {
|
||||
var errT = discardErr();
|
||||
var string = new String(getStdout().readAllBytes(), getCharset());
|
||||
waitFor();
|
||||
return string;
|
||||
return string.trim();
|
||||
}
|
||||
|
||||
public Optional<String> readErrOnly() throws Exception {
|
||||
@@ -34,7 +34,7 @@ public abstract class ProcessControl {
|
||||
t.start();
|
||||
|
||||
var ec = waitFor();
|
||||
return ec != 0 ? Optional.of(read.get()) : Optional.empty();
|
||||
return ec != 0 ? Optional.of(read.get().trim()) : Optional.empty();
|
||||
}
|
||||
|
||||
public Thread discardOut() {
|
||||
|
||||
@@ -2,28 +2,23 @@ package io.xpipe.core.store;
|
||||
|
||||
import io.xpipe.core.util.SecretValue;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public abstract class ShellStore implements DataStore {
|
||||
public interface ShellStore extends DataStore {
|
||||
|
||||
public Integer getTimeout() {
|
||||
public default Integer getTimeout() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<SecretValue> getInput() {
|
||||
public default List<SecretValue> getInput() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String executeAndRead(List<String> cmd, Integer timeout) throws Exception {
|
||||
public default String executeAndRead(List<String> cmd, Integer timeout) throws Exception {
|
||||
var pc = prepareCommand(List.of(), cmd, getEffectiveTimeOut(timeout));
|
||||
pc.start();
|
||||
pc.discardErr();
|
||||
@@ -31,7 +26,8 @@ public abstract class ShellStore implements DataStore {
|
||||
return string;
|
||||
}
|
||||
|
||||
public String executeAndCheckOut(List<SecretValue> in, List<String> cmd, Integer timeout) throws ProcessOutputException, Exception {
|
||||
public default String executeAndCheckOut(List<SecretValue> in, List<String> cmd, Integer timeout)
|
||||
throws ProcessOutputException, Exception {
|
||||
var pc = prepareCommand(in, cmd, getEffectiveTimeOut(timeout));
|
||||
pc.start();
|
||||
|
||||
@@ -47,15 +43,10 @@ public abstract class ShellStore implements DataStore {
|
||||
errorThread.setDaemon(true);
|
||||
errorThread.start();
|
||||
|
||||
var read = new ByteArrayOutputStream();
|
||||
AtomicReference<String> read = new AtomicReference<>();
|
||||
var t = new Thread(() -> {
|
||||
try {
|
||||
final byte[] buf = new byte[1];
|
||||
|
||||
int length;
|
||||
while ((length = pc.getStdout().read(buf)) > 0) {
|
||||
read.write(buf, 0, length);
|
||||
}
|
||||
read.set(new String(pc.getStdout().readAllBytes(), pc.getCharset()));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
@@ -64,19 +55,18 @@ public abstract class ShellStore implements DataStore {
|
||||
t.start();
|
||||
|
||||
var ec = pc.waitFor();
|
||||
var readOut = read.toString(pc.getCharset());
|
||||
if (ec == -1) {
|
||||
throw new ProcessOutputException("Command timed out");
|
||||
}
|
||||
|
||||
if (ec == 0) {
|
||||
return readOut;
|
||||
if (ec == 0 && !(read.get().isEmpty() && !readError.get().isEmpty())) {
|
||||
return read.get().trim();
|
||||
} else {
|
||||
throw new ProcessOutputException("Command returned with " + ec + ": " + readError.get());
|
||||
throw new ProcessOutputException("Command returned with " + ec + ": " + readError.get().trim());
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<String> executeAndCheckErr(List<SecretValue> in, List<String> cmd) throws Exception {
|
||||
public default Optional<String> executeAndCheckErr(List<SecretValue> in, List<String> cmd) throws Exception {
|
||||
var pc = prepareCommand(in, cmd, getTimeout());
|
||||
pc.start();
|
||||
var outT = pc.discardOut();
|
||||
@@ -99,7 +89,7 @@ public abstract class ShellStore implements DataStore {
|
||||
return ec != 0 ? Optional.of(read.get()) : Optional.empty();
|
||||
}
|
||||
|
||||
public Integer getEffectiveTimeOut(Integer timeout) {
|
||||
public default Integer getEffectiveTimeOut(Integer timeout) {
|
||||
if (this.getTimeout() == null) {
|
||||
return timeout;
|
||||
}
|
||||
@@ -109,17 +99,19 @@ public abstract class ShellStore implements DataStore {
|
||||
return Math.min(getTimeout(), timeout);
|
||||
}
|
||||
|
||||
public ProcessControl prepareCommand(List<String> cmd, Integer timeout) throws Exception {
|
||||
public default ProcessControl prepareCommand(List<String> cmd, Integer timeout) throws Exception {
|
||||
return prepareCommand(List.of(), cmd, timeout);
|
||||
}
|
||||
|
||||
public abstract ProcessControl prepareCommand(List<SecretValue> input, List<String> cmd, Integer timeout) throws Exception;
|
||||
public abstract ProcessControl prepareCommand(List<SecretValue> input, List<String> cmd, Integer timeout)
|
||||
throws Exception;
|
||||
|
||||
public ProcessControl preparePrivilegedCommand(List<String> cmd, Integer timeout) throws Exception {
|
||||
public default ProcessControl preparePrivilegedCommand(List<String> cmd, Integer timeout) throws Exception {
|
||||
return preparePrivilegedCommand(List.of(), cmd, timeout);
|
||||
}
|
||||
|
||||
public ProcessControl preparePrivilegedCommand(List<SecretValue> input, List<String> cmd, Integer timeout) throws Exception {
|
||||
public default ProcessControl preparePrivilegedCommand(List<SecretValue> input, List<String> cmd, Integer timeout)
|
||||
throws Exception {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +77,10 @@ public class ShellTypes {
|
||||
var l = new ArrayList<>(cmd);
|
||||
l.add(0, "cmd.exe");
|
||||
l.add(1, "/c");
|
||||
l.add(2, "@chcp 65001>nul");
|
||||
l.add(3, "&&");
|
||||
l.add(2, "@chcp 65001");
|
||||
l.add(3, ">");
|
||||
l.add(4, "nul");
|
||||
l.add(5, "&&");
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,11 @@ import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class StandardShellStore extends ShellStore implements MachineFileStore {
|
||||
public interface StandardShellStore extends MachineFileStore, ShellStore {
|
||||
|
||||
public default boolean isLocal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
public static interface ShellType {
|
||||
@@ -38,19 +42,19 @@ public abstract class StandardShellStore extends ShellStore implements MachineFi
|
||||
}
|
||||
|
||||
|
||||
public NewLine getNewLine() throws Exception {
|
||||
public default NewLine getNewLine() throws Exception {
|
||||
return determineType().getNewLine();
|
||||
}
|
||||
|
||||
public abstract ShellType determineType() throws Exception;
|
||||
|
||||
public final String querySystemName() throws Exception {
|
||||
public default String querySystemName() throws Exception {
|
||||
var result = executeAndCheckOut(List.of(), determineType().getOperatingSystemNameCommand(), getTimeout());
|
||||
return result.strip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream openInput(String file) throws Exception {
|
||||
public default InputStream openInput(String file) throws Exception {
|
||||
var type = determineType();
|
||||
var cmd = type.createFileReadCommand(file);
|
||||
var p = prepareCommand(List.of(), cmd, null);
|
||||
@@ -59,7 +63,7 @@ public abstract class StandardShellStore extends ShellStore implements MachineFi
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream openOutput(String file) throws Exception {
|
||||
public default OutputStream openOutput(String file) throws Exception {
|
||||
return null;
|
||||
// var type = determineType();
|
||||
// var cmd = type.createFileWriteCommand(file);
|
||||
@@ -69,7 +73,8 @@ public abstract class StandardShellStore extends ShellStore implements MachineFi
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(String file) throws Exception {
|
||||
|
||||
public default boolean exists(String file) throws Exception {
|
||||
var type = determineType();
|
||||
var cmd = type.createFileExistsCommand(file);
|
||||
var p = prepareCommand(List.of(), cmd, null);
|
||||
@@ -78,7 +83,7 @@ public abstract class StandardShellStore extends ShellStore implements MachineFi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mkdirs(String file) throws Exception {
|
||||
public default void mkdirs(String file) throws Exception {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
import io.xpipe.core.util.JacksonizedValue;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
@EqualsAndHashCode
|
||||
@Value
|
||||
@JsonTypeName("stdin")
|
||||
public class StdinDataStore implements StreamDataStore {
|
||||
@SuperBuilder
|
||||
public class StdinDataStore extends JacksonizedValue implements StreamDataStore {
|
||||
|
||||
@Override
|
||||
public boolean isContentExclusivelyAccessible() {
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
import io.xpipe.core.util.JacksonizedValue;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
@EqualsAndHashCode
|
||||
@Value
|
||||
@JsonTypeName("stdout")
|
||||
public class StdoutDataStore implements StreamDataStore {
|
||||
@SuperBuilder
|
||||
public class StdoutDataStore extends JacksonizedValue implements StreamDataStore {
|
||||
|
||||
@Override
|
||||
public boolean canOpen() throws Exception {
|
||||
|
||||
@@ -10,35 +10,40 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
public class JacksonHelper {
|
||||
public class JacksonMapper {
|
||||
|
||||
private static final ObjectMapper BASE = new ObjectMapper();
|
||||
private static ObjectMapper INSTANCE = new ObjectMapper();
|
||||
private static final ObjectMapper DEFAULT;
|
||||
private static boolean init = false;
|
||||
private static List<Module> MODULES;
|
||||
|
||||
public static synchronized void initClassBased() {
|
||||
initModularized(null);
|
||||
}
|
||||
|
||||
public static synchronized void initModularized(ModuleLayer layer) {
|
||||
MODULES = findModules(layer);
|
||||
|
||||
static {
|
||||
ObjectMapper objectMapper = BASE;
|
||||
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
|
||||
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
||||
objectMapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
|
||||
objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
|
||||
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
|
||||
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withIsGetterVisibility(JsonAutoDetect.Visibility.NONE));
|
||||
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
|
||||
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withIsGetterVisibility(JsonAutoDetect.Visibility.NONE));
|
||||
|
||||
var modules = findModules(ModuleLayer.boot());
|
||||
objectMapper.registerModules(modules);
|
||||
|
||||
INSTANCE = BASE.copy();
|
||||
INSTANCE.registerModules(MODULES);
|
||||
DEFAULT = BASE.copy();
|
||||
}
|
||||
|
||||
public static synchronized void initClassBased() {
|
||||
initModularized(null);
|
||||
}
|
||||
|
||||
public static synchronized void initModularized(ModuleLayer layer) {
|
||||
List<Module> MODULES = findModules(layer);
|
||||
INSTANCE.registerModules(MODULES);
|
||||
init = true;
|
||||
}
|
||||
|
||||
@@ -56,8 +61,8 @@ public class JacksonHelper {
|
||||
* Constructs a new ObjectMapper that is able to map all required X-Pipe classes and also possible extensions.
|
||||
*/
|
||||
public static ObjectMapper newMapper() {
|
||||
if (!JacksonHelper.isInit()) {
|
||||
JacksonHelper.initModularized(ModuleLayer.boot());
|
||||
if (!JacksonMapper.isInit()) {
|
||||
return DEFAULT;
|
||||
}
|
||||
return INSTANCE.copy();
|
||||
}
|
||||
38
core/src/main/java/io/xpipe/core/util/JacksonizedValue.java
Normal file
38
core/src/main/java/io/xpipe/core/util/JacksonizedValue.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package io.xpipe.core.util;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
@SuperBuilder
|
||||
public class JacksonizedValue {
|
||||
|
||||
public JacksonizedValue() {
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public final String toString() {
|
||||
var tree = JacksonMapper.newMapper().valueToTree(this);
|
||||
return tree.toPrettyString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o != null && getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var tree = JacksonMapper.newMapper().valueToTree(this);
|
||||
var otherTree = JacksonMapper.newMapper().valueToTree(o);
|
||||
return tree.equals(otherTree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
var tree = JacksonMapper.newMapper().valueToTree(this);
|
||||
return tree.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,7 +36,10 @@ public class SecretValue {
|
||||
if (value.length() < 2) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return new String(Base64.getDecoder().decode(value), StandardCharsets.UTF_8);
|
||||
try {
|
||||
return new String(Base64.getDecoder().decode(value), StandardCharsets.UTF_8);
|
||||
} catch (Exception exception) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user