mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-25 17:10:27 +00:00
Large refactor
This commit is contained in:
parent
9440037f03
commit
3cc527dfa3
76 changed files with 359 additions and 387 deletions
13
README.md
13
README.md
|
@ -1,5 +1,6 @@
|
||||||
## X-Pipe Java
|
## X-Pipe Java
|
||||||
|
|
||||||
|
The fundamental components of the [X-Pipe project]().
|
||||||
This repository contains the following four modules:
|
This repository contains the following four modules:
|
||||||
|
|
||||||
- Core - Shared core classes of the Java API and the X-Pipe daemon implementation
|
- Core - Shared core classes of the Java API and the X-Pipe daemon implementation
|
||||||
|
@ -8,6 +9,18 @@ This repository contains the following four modules:
|
||||||
and the client applications, for example the various programming language APIs and the CLI
|
and the client applications, for example the various programming language APIs and the CLI
|
||||||
- Extension - An API to create all different kinds of extensions for the X-Pipe platform
|
- Extension - An API to create all different kinds of extensions for the X-Pipe platform
|
||||||
|
|
||||||
|
## Installation / Usage
|
||||||
|
|
||||||
|
The *core* and *extension* libraries are used in X-Pipe extension development.
|
||||||
|
For setup instructions, see the [X-Pipe extension development]() section.
|
||||||
|
|
||||||
|
The *beacon* library handles all communication and serves as a
|
||||||
|
reference when implementing an API or program that communicates with the X-Pipe daemon.
|
||||||
|
|
||||||
|
The *api* library serves as a reference implementation for other potential X-Pipe APIs
|
||||||
|
and is also used to enable your Java program to communicate with X-Pipe.
|
||||||
|
For setup instructions, see the [X-Pipe Java API Usage]() section.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
All X-Pipe components target [JDK 17](https://openjdk.java.net/projects/jdk/17/) and make full use of the Java Module System (JPMS).
|
All X-Pipe components target [JDK 17](https://openjdk.java.net/projects/jdk/17/) and make full use of the Java Module System (JPMS).
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.xpipe/api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.xpipe/api)
|
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.xpipe/api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.xpipe/api)
|
||||||
[![javadoc](https://javadoc.io/badge2/io.xpipe/api/javadoc.svg)](https://javadoc.io/doc/io.xpipe/api)
|
[![javadoc](https://javadoc.io/badge2/io.xpipe/api/javadoc.svg)](https://javadoc.io/doc/io.xpipe/api)
|
||||||
[![Build Status](https://github.com/xpipe-io/xpipe_java/actions/workflows/api-build.yml/badge.svg)](https://github.com/xpipe-io/xpipe_java/actions/workflows/api-build.yml)
|
[![Build Status](https://github.com/xpipe-io/xpipe_java/actions/workflows/api-build.yml/badge.svg)](https://github.com/xpipe-io/xpipe_java/actions/workflows/api-build.yml)
|
||||||
|
|
||||||
|
## X-Pipe Java API
|
||||||
|
|
||||||
|
The X-Pipe API for Java allows you to use most of the X-Pipe functionality from Java applications:
|
||||||
|
|
||||||
|
- Create data stores and data sources
|
||||||
|
- Query and work with the contents of data sources
|
||||||
|
- Write and append to data sources
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Either install the [dependency](https://maven-badges.herokuapp.com/maven-central/io.xpipe/api) from Maven Central
|
||||||
|
using your favourite build tool or alternatively download the `xpipe-api.jar`, `xpipe-core.jar`, and `xpipe-beacon.jar`
|
||||||
|
from the [releases page](https://github.com/xpipe-io/xpipe_java/releases/latest) and add them to the classpath.
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ public interface DataSource {
|
||||||
DataSourceType getType();
|
DataSourceType getType();
|
||||||
|
|
||||||
|
|
||||||
DataSourceConfigInstance getConfig();
|
DataSourceConfig getConfig();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to cast this object to a {@link DataTable}.
|
* Attempts to cast this object to a {@link DataTable}.
|
||||||
|
|
32
api/src/main/java/io/xpipe/api/DataSourceConfig.java
Normal file
32
api/src/main/java/io/xpipe/api/DataSourceConfig.java
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package io.xpipe.api;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the current configuration of a data source.
|
||||||
|
*/
|
||||||
|
public final class DataSourceConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data source provider id.
|
||||||
|
*/
|
||||||
|
private final String provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set configuration parameters.
|
||||||
|
*/
|
||||||
|
private final Map<String, String> configInstance;
|
||||||
|
|
||||||
|
public DataSourceConfig(String provider, Map<String, String> configInstance) {
|
||||||
|
this.provider = provider;
|
||||||
|
this.configInstance = configInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProvider() {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getConfigInstance() {
|
||||||
|
return configInstance;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package io.xpipe.api.impl;
|
package io.xpipe.api.impl;
|
||||||
|
|
||||||
import io.xpipe.api.DataRaw;
|
import io.xpipe.api.DataRaw;
|
||||||
|
import io.xpipe.api.DataSourceConfig;
|
||||||
import io.xpipe.core.source.*;
|
import io.xpipe.core.source.*;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -9,7 +10,7 @@ public class DataRawImpl extends DataSourceImpl implements DataRaw {
|
||||||
|
|
||||||
private final DataSourceInfo.Raw info;
|
private final DataSourceInfo.Raw info;
|
||||||
|
|
||||||
public DataRawImpl(DataSourceId sourceId, DataSourceConfigInstance sourceConfig, DataSourceInfo.Raw info) {
|
public DataRawImpl(DataSourceId sourceId, DataSourceConfig sourceConfig, DataSourceInfo.Raw info) {
|
||||||
super(sourceId, sourceConfig);
|
super(sourceId, sourceConfig);
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package io.xpipe.api.impl;
|
package io.xpipe.api.impl;
|
||||||
|
|
||||||
import io.xpipe.api.DataSource;
|
import io.xpipe.api.DataSource;
|
||||||
|
import io.xpipe.api.DataSourceConfig;
|
||||||
import io.xpipe.api.connector.XPipeConnection;
|
import io.xpipe.api.connector.XPipeConnection;
|
||||||
import io.xpipe.beacon.exchange.StoreStreamExchange;
|
|
||||||
import io.xpipe.beacon.exchange.QueryDataSourceExchange;
|
import io.xpipe.beacon.exchange.QueryDataSourceExchange;
|
||||||
import io.xpipe.beacon.exchange.ReadExecuteExchange;
|
|
||||||
import io.xpipe.beacon.exchange.ReadPreparationExchange;
|
import io.xpipe.beacon.exchange.ReadPreparationExchange;
|
||||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
import io.xpipe.beacon.exchange.StoreStreamExchange;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
|
|
||||||
|
@ -19,22 +18,23 @@ public abstract class DataSourceImpl implements DataSource {
|
||||||
return XPipeConnection.execute(con -> {
|
return XPipeConnection.execute(con -> {
|
||||||
var req = QueryDataSourceExchange.Request.builder().ref(ds).build();
|
var req = QueryDataSourceExchange.Request.builder().ref(ds).build();
|
||||||
QueryDataSourceExchange.Response res = con.performSimpleExchange(req);
|
QueryDataSourceExchange.Response res = con.performSimpleExchange(req);
|
||||||
|
var config = new DataSourceConfig(res.getProvider(), res.getConfig());
|
||||||
switch (res.getInfo().getType()) {
|
switch (res.getInfo().getType()) {
|
||||||
case TABLE -> {
|
case TABLE -> {
|
||||||
var data = res.getInfo().asTable();
|
var data = res.getInfo().asTable();
|
||||||
return new DataTableImpl(res.getId(), res.getConfig(), data);
|
return new DataTableImpl(res.getId(), config, data);
|
||||||
}
|
}
|
||||||
case STRUCTURE -> {
|
case STRUCTURE -> {
|
||||||
var info = res.getInfo().asStructure();
|
var info = res.getInfo().asStructure();
|
||||||
return new DataStructureImpl(res.getId(), res.getConfig(), info);
|
return new DataStructureImpl(res.getId(), config, info);
|
||||||
}
|
}
|
||||||
case TEXT -> {
|
case TEXT -> {
|
||||||
var info = res.getInfo().asText();
|
var info = res.getInfo().asText();
|
||||||
return new DataTextImpl(res.getId(), res.getConfig(), info);
|
return new DataTextImpl(res.getId(), config, info);
|
||||||
}
|
}
|
||||||
case RAW -> {
|
case RAW -> {
|
||||||
var info = res.getInfo().asRaw();
|
var info = res.getInfo().asRaw();
|
||||||
return new DataRawImpl(res.getId(), res.getConfig(), info);
|
return new DataRawImpl(res.getId(), config, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
|
@ -60,20 +60,21 @@ public abstract class DataSourceImpl implements DataSource {
|
||||||
});
|
});
|
||||||
|
|
||||||
var configInstance = startRes.getConfig();
|
var configInstance = startRes.getConfig();
|
||||||
configInstance.getConfigInstance().getCurrentValues().putAll(config);
|
//TODO
|
||||||
var endReq = ReadExecuteExchange.Request.builder()
|
// configInstance.getConfigInstance().getCurrentValues().putAll(config);
|
||||||
.target(id).dataStore(store).config(configInstance).build();
|
// var endReq = ReadExecuteExchange.Request.builder()
|
||||||
XPipeConnection.execute(con -> {
|
// .target(id).dataStore(store).config(configInstance).build();
|
||||||
con.performSimpleExchange(endReq);
|
// XPipeConnection.execute(con -> {
|
||||||
});
|
// con.performSimpleExchange(endReq);
|
||||||
|
// });
|
||||||
var ref = id != null ? DataSourceReference.id(id) : DataSourceReference.latest();
|
var ref = id != null ? DataSourceReference.id(id) : DataSourceReference.latest();
|
||||||
return get(ref);
|
return get(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final DataSourceId sourceId;
|
private final DataSourceId sourceId;
|
||||||
private final DataSourceConfigInstance config;
|
private final DataSourceConfig config;
|
||||||
|
|
||||||
public DataSourceImpl(DataSourceId sourceId, DataSourceConfigInstance config) {
|
public DataSourceImpl(DataSourceId sourceId, DataSourceConfig config) {
|
||||||
this.sourceId = sourceId;
|
this.sourceId = sourceId;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +85,7 @@ public abstract class DataSourceImpl implements DataSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataSourceConfigInstance getConfig() {
|
public DataSourceConfig getConfig() {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.api.impl;
|
package io.xpipe.api.impl;
|
||||||
|
|
||||||
|
import io.xpipe.api.DataSourceConfig;
|
||||||
import io.xpipe.api.DataStructure;
|
import io.xpipe.api.DataStructure;
|
||||||
import io.xpipe.core.data.node.DataStructureNode;
|
import io.xpipe.core.data.node.DataStructureNode;
|
||||||
import io.xpipe.core.source.*;
|
import io.xpipe.core.source.*;
|
||||||
|
@ -8,7 +9,7 @@ public class DataStructureImpl extends DataSourceImpl implements DataStructure {
|
||||||
|
|
||||||
private final DataSourceInfo.Structure info;
|
private final DataSourceInfo.Structure info;
|
||||||
|
|
||||||
public DataStructureImpl(DataSourceId sourceId, DataSourceConfigInstance sourceConfig, DataSourceInfo.Structure info) {
|
public DataStructureImpl(DataSourceId sourceId, DataSourceConfig sourceConfig, DataSourceInfo.Structure info) {
|
||||||
super(sourceId, sourceConfig);
|
super(sourceId, sourceConfig);
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,13 @@ import io.xpipe.api.DataTable;
|
||||||
import io.xpipe.api.DataTableAccumulator;
|
import io.xpipe.api.DataTableAccumulator;
|
||||||
import io.xpipe.api.connector.XPipeConnection;
|
import io.xpipe.api.connector.XPipeConnection;
|
||||||
import io.xpipe.api.util.TypeDescriptor;
|
import io.xpipe.api.util.TypeDescriptor;
|
||||||
import io.xpipe.beacon.exchange.StoreStreamExchange;
|
|
||||||
import io.xpipe.beacon.exchange.ReadExecuteExchange;
|
import io.xpipe.beacon.exchange.ReadExecuteExchange;
|
||||||
|
import io.xpipe.beacon.exchange.StoreStreamExchange;
|
||||||
import io.xpipe.core.data.node.DataStructureNode;
|
import io.xpipe.core.data.node.DataStructureNode;
|
||||||
import io.xpipe.core.data.node.DataStructureNodeAcceptor;
|
import io.xpipe.core.data.node.DataStructureNodeAcceptor;
|
||||||
import io.xpipe.core.data.node.TupleNode;
|
import io.xpipe.core.data.node.TupleNode;
|
||||||
import io.xpipe.core.data.type.TupleType;
|
import io.xpipe.core.data.type.TupleType;
|
||||||
import io.xpipe.core.data.typed.TypedDataStreamWriter;
|
import io.xpipe.core.data.typed.TypedDataStreamWriter;
|
||||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ public class DataTableAccumulatorImpl implements DataTableAccumulator {
|
||||||
connection.close();
|
connection.close();
|
||||||
|
|
||||||
var req = ReadExecuteExchange.Request.builder()
|
var req = ReadExecuteExchange.Request.builder()
|
||||||
.target(id).dataStore(res.getStore()).config(DataSourceConfigInstance.xpbt()).build();
|
.target(id).dataStore(res.getStore()).build();
|
||||||
XPipeConnection.execute(con -> {
|
XPipeConnection.execute(con -> {
|
||||||
con.performSimpleExchange(req);
|
con.performSimpleExchange(req);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.api.impl;
|
package io.xpipe.api.impl;
|
||||||
|
|
||||||
|
import io.xpipe.api.DataSourceConfig;
|
||||||
import io.xpipe.api.DataTable;
|
import io.xpipe.api.DataTable;
|
||||||
import io.xpipe.api.connector.XPipeConnection;
|
import io.xpipe.api.connector.XPipeConnection;
|
||||||
import io.xpipe.beacon.BeaconConnection;
|
import io.xpipe.beacon.BeaconConnection;
|
||||||
|
@ -24,7 +25,7 @@ public class DataTableImpl extends DataSourceImpl implements DataTable {
|
||||||
|
|
||||||
private final DataSourceInfo.Table info;
|
private final DataSourceInfo.Table info;
|
||||||
|
|
||||||
DataTableImpl(DataSourceId id, DataSourceConfigInstance sourceConfig, DataSourceInfo.Table info) {
|
DataTableImpl(DataSourceId id, DataSourceConfig sourceConfig, DataSourceInfo.Table info) {
|
||||||
super(id, sourceConfig);
|
super(id, sourceConfig);
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.api.impl;
|
package io.xpipe.api.impl;
|
||||||
|
|
||||||
|
import io.xpipe.api.DataSourceConfig;
|
||||||
import io.xpipe.api.DataText;
|
import io.xpipe.api.DataText;
|
||||||
import io.xpipe.core.source.*;
|
import io.xpipe.core.source.*;
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@ public class DataTextImpl extends DataSourceImpl implements DataText {
|
||||||
|
|
||||||
private final DataSourceInfo.Text info;
|
private final DataSourceInfo.Text info;
|
||||||
|
|
||||||
public DataTextImpl(DataSourceId sourceId, DataSourceConfigInstance sourceConfig, DataSourceInfo.Text info) {
|
public DataTextImpl(DataSourceId sourceId, DataSourceConfig sourceConfig, DataSourceInfo.Text info) {
|
||||||
super(sourceId, sourceConfig);
|
super(sourceId, sourceConfig);
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
The X-Pipe beacon component is responsible for handling all communications between the X-Pipe daemon
|
The X-Pipe beacon component is responsible for handling all communications between the X-Pipe daemon
|
||||||
and the various programming language APIs and the CLI. It provides an API that supports all kinds
|
and the various programming language APIs and the CLI. It provides an API that supports all kinds
|
||||||
of different operations.
|
of different operations.
|
||||||
The underlying inter-process communication is realized through TCP sockets on port `21721`.
|
The underlying inter-process communication is realized through TCP sockets on default port `21721`.
|
||||||
|
|
||||||
The data structures and exchange protocols are specified in the `io.xpipe.beacon.exchange` package.
|
The data structures and exchange protocols are specified in the `io.xpipe.beacon.exchange` package.
|
||||||
Every exchange is initiated from the outside by sending a request message to the daemon.
|
Every exchange is initiated from the outside by sending a request message to the X-Pipe daemon.
|
||||||
The daemon then always sends a response message.
|
The daemon then always sends a response message.
|
||||||
|
|
||||||
The header information of a message is formatted in the json format.
|
The header information of a message is formatted in the json format.
|
||||||
|
@ -23,7 +23,7 @@ Each segment is preceded by four bytes that specify the length of the next segme
|
||||||
In case the next segment has a length of less than `65536` bytes, we know that the end of the body has been reached.
|
In case the next segment has a length of less than `65536` bytes, we know that the end of the body has been reached.
|
||||||
This way the socket communication can handle payloads of unknown length.
|
This way the socket communication can handle payloads of unknown length.
|
||||||
|
|
||||||
### Configuration
|
## Configuration
|
||||||
|
|
||||||
The default port used by the beacon implementation of the X-Pipe daemon and APIs is `21721`.
|
The default port used by the beacon implementation of the X-Pipe daemon and APIs is `21721`.
|
||||||
It can be changed by passing the property `io.xpipe.beacon.port=<port>` to both the daemon and APIs.
|
It can be changed by passing the property `io.xpipe.beacon.port=<port>` to both the daemon and APIs.
|
||||||
|
@ -32,6 +32,7 @@ The beacon API also supports launching the daemon automatically in case it is no
|
||||||
By default, it launches the daemon of the local X-Pipe installation.
|
By default, it launches the daemon of the local X-Pipe installation.
|
||||||
It is possible to pass a custom launch command with the property `io.xpipe.beacon.exec=<cmd>`.
|
It is possible to pass a custom launch command with the property `io.xpipe.beacon.exec=<cmd>`.
|
||||||
This allows for a custom launch behaviour in a testing/development environment.
|
This allows for a custom launch behaviour in a testing/development environment.
|
||||||
|
Note that the `<cmd>` value has to be a single property string, which can be prone to formatting errors
|
||||||
|
|
||||||
By passing the property `io.xpipe.beacon.debugOutput=true`, it is possible to print debug information
|
By passing the property `io.xpipe.beacon.debugOutput=true`, it is possible to print debug information
|
||||||
about the underlying communications.
|
about the underlying communications.
|
||||||
|
|
|
@ -8,8 +8,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.fasterxml.jackson.databind.node.TextNode;
|
import com.fasterxml.jackson.databind.node.TextNode;
|
||||||
import io.xpipe.beacon.exchange.MessageExchanges;
|
import io.xpipe.beacon.exchange.MessageExchanges;
|
||||||
import io.xpipe.beacon.exchange.data.ClientErrorMessage;
|
import io.xpipe.beacon.exchange.data.ClientErrorMessage;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
|
||||||
import io.xpipe.beacon.exchange.data.ServerErrorMessage;
|
import io.xpipe.beacon.exchange.data.ServerErrorMessage;
|
||||||
import io.xpipe.core.util.JacksonHelper;
|
import io.xpipe.core.util.JacksonHelper;
|
||||||
|
|
||||||
|
@ -32,12 +30,6 @@ public class BeaconClient implements AutoCloseable {
|
||||||
void accept(T var1, U var2) throws E;
|
void accept(T var1, U var2) throws E;
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface FailableBiPredicate<T, U, E extends Throwable> {
|
|
||||||
|
|
||||||
boolean test(T var1, U var2) throws E;
|
|
||||||
}
|
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface FailableConsumer<T, E extends Throwable> {
|
public interface FailableConsumer<T, E extends Throwable> {
|
||||||
|
|
||||||
|
@ -76,30 +68,6 @@ public class BeaconClient implements AutoCloseable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <REQ extends RequestMessage, RES extends ResponseMessage> void exchange(
|
|
||||||
REQ req,
|
|
||||||
FailableConsumer<OutputStream, IOException> reqWriter,
|
|
||||||
FailableBiConsumer<RES, InputStream, IOException> resReader)
|
|
||||||
throws ConnectorException, ClientException, ServerException {
|
|
||||||
try {
|
|
||||||
sendRequest(req);
|
|
||||||
if (reqWriter != null) {
|
|
||||||
out.write(BODY_SEPARATOR);
|
|
||||||
reqWriter.accept(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
var res = this.<RES>receiveResponse();
|
|
||||||
var sep = in.readNBytes(BODY_SEPARATOR.length);
|
|
||||||
if (sep.length != 0 && !Arrays.equals(BODY_SEPARATOR, sep)) {
|
|
||||||
throw new ConnectorException("Invalid body separator");
|
|
||||||
}
|
|
||||||
|
|
||||||
resReader.accept(res, in);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new ConnectorException("Couldn't communicate with socket", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream receiveBody() throws ConnectorException {
|
public InputStream receiveBody() throws ConnectorException {
|
||||||
try {
|
try {
|
||||||
var sep = in.readNBytes(BODY_SEPARATOR.length);
|
var sep = in.readNBytes(BODY_SEPARATOR.length);
|
||||||
|
@ -238,16 +206,4 @@ public class BeaconClient implements AutoCloseable {
|
||||||
throw new ConnectorException("Couldn't parse response", ex);
|
throw new ConnectorException("Couldn't parse response", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInputStream() {
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OutputStream getOutputStream() {
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Socket getSocket() {
|
|
||||||
return socket;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
|
@ -13,7 +13,7 @@ import java.nio.file.Path;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains basic functionality to start, communicate, and stop a beacon server.
|
* Contains basic functionality to start, communicate, and stop a remote beacon server.
|
||||||
*/
|
*/
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class BeaconServer {
|
public class BeaconServer {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package io.xpipe.beacon.message;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
public interface RequestMessage {
|
public interface RequestMessage {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
|
public interface ResponseMessage {
|
||||||
|
|
||||||
|
}
|
|
@ -1,11 +1,8 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
import lombok.experimental.StandardException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that an internal server error occurred.
|
* Indicates that an internal server error occurred.
|
||||||
*/
|
*/
|
||||||
@StandardException
|
|
||||||
public class ServerException extends Exception {
|
public class ServerException extends Exception {
|
||||||
|
|
||||||
public ServerException() {
|
public ServerException() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange;
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.dialog.DialogReference;
|
import io.xpipe.core.dialog.DialogReference;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange;
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
@ -15,26 +15,23 @@ public class MessageExchanges {
|
||||||
private static void loadAll() {
|
private static void loadAll() {
|
||||||
if (ALL == null) {
|
if (ALL == null) {
|
||||||
ALL = ServiceLoader.load(MessageExchange.class).stream()
|
ALL = ServiceLoader.load(MessageExchange.class).stream()
|
||||||
.map(s -> (MessageExchange) s.get()).collect(Collectors.toSet());
|
.map(ServiceLoader.Provider::get).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange> byId(String name) {
|
public static Optional<MessageExchange> byId(String name) {
|
||||||
loadAll();
|
loadAll();
|
||||||
var r = ALL.stream().filter(d -> d.getId().equals(name)).findAny();
|
return ALL.stream().filter(d -> d.getId().equals(name)).findAny();
|
||||||
return Optional.ofNullable((MessageExchange) r.orElse(null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange> byRequest(RQ req) {
|
public static <RQ extends RequestMessage> Optional<MessageExchange> byRequest(RQ req) {
|
||||||
loadAll();
|
loadAll();
|
||||||
var r = ALL.stream().filter(d -> d.getRequestClass().equals(req.getClass())).findAny();
|
return ALL.stream().filter(d -> d.getRequestClass().equals(req.getClass())).findAny();
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange> byResponse(RP rep) {
|
public static <RP extends ResponseMessage> Optional<MessageExchange> byResponse(RP rep) {
|
||||||
loadAll();
|
loadAll();
|
||||||
var r = ALL.stream().filter(d -> d.getResponseClass().equals(rep.getClass())).findAny();
|
return ALL.stream().filter(d -> d.getResponseClass().equals(rep.getClass())).findAny();
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<MessageExchange> getAll() {
|
public static Set<MessageExchange> getAll() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange;
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.source.DataSourceInfo;
|
import io.xpipe.core.source.DataSourceInfo;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange;
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.store.DataStore;
|
import io.xpipe.core.store.DataStore;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
@ -26,8 +25,6 @@ public class ReadExecuteExchange implements MessageExchange {
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {
|
||||||
@NonNull
|
@NonNull
|
||||||
DataStore dataStore;
|
DataStore dataStore;
|
||||||
@NonNull
|
|
||||||
DataSourceConfigInstance config;
|
|
||||||
|
|
||||||
DataSourceId target;
|
DataSourceId target;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange;
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.dialog.DialogReference;
|
import io.xpipe.core.dialog.DialogReference;
|
||||||
import io.xpipe.core.store.DataStore;
|
import io.xpipe.core.store.DataStore;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange;
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange;
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.store.FileStore;
|
import io.xpipe.core.store.FileStore;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.api;
|
package io.xpipe.beacon.exchange.api;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.api;
|
package io.xpipe.beacon.exchange.api;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.api;
|
package io.xpipe.beacon.exchange.api;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.dialog.DialogReference;
|
import io.xpipe.core.dialog.DialogReference;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.dialog.DialogElement;
|
import io.xpipe.core.dialog.DialogElement;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
|
@ -2,8 +2,8 @@ package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.exchange.data.CollectionListEntry;
|
import io.xpipe.beacon.exchange.data.CollectionListEntry;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
|
@ -2,8 +2,8 @@ package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.exchange.data.EntryListEntry;
|
import io.xpipe.beacon.exchange.data.EntryListEntry;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
|
@ -2,8 +2,8 @@ package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.exchange.data.StoreListEntry;
|
import io.xpipe.beacon.exchange.data.StoreListEntry;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
|
@ -2,8 +2,8 @@ package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.exchange.data.ProviderEntry;
|
import io.xpipe.beacon.exchange.data.ProviderEntry;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceType;
|
import io.xpipe.core.source.DataSourceType;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.dialog.DialogReference;
|
import io.xpipe.core.dialog.DialogReference;
|
||||||
import io.xpipe.core.store.DataStore;
|
import io.xpipe.core.store.DataStore;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
@ -26,9 +25,6 @@ public class WriteExecuteExchange implements MessageExchange {
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {
|
||||||
@NonNull
|
@NonNull
|
||||||
DataSourceReference ref;
|
DataSourceReference ref;
|
||||||
|
|
||||||
@NonNull
|
|
||||||
DataSourceConfigInstance config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
import io.xpipe.core.dialog.DialogReference;
|
import io.xpipe.core.dialog.DialogReference;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import io.xpipe.core.store.StreamDataStore;
|
import io.xpipe.core.store.StreamDataStore;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
@SuppressWarnings("ClassCanBeRecord")
|
||||||
@Value
|
@Value
|
||||||
@Builder
|
@Builder
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
|
|
|
@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@SuppressWarnings("ClassCanBeRecord")
|
||||||
@Value
|
@Value
|
||||||
@Builder
|
@Builder
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
package io.xpipe.beacon.message;
|
|
||||||
|
|
||||||
import io.xpipe.beacon.BeaconHandler;
|
|
||||||
|
|
||||||
public interface ResponseMessage {
|
|
||||||
|
|
||||||
default void postSend(BeaconHandler handler) throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,6 @@ import io.xpipe.beacon.exchange.cli.*;
|
||||||
module io.xpipe.beacon {
|
module io.xpipe.beacon {
|
||||||
exports io.xpipe.beacon;
|
exports io.xpipe.beacon;
|
||||||
exports io.xpipe.beacon.exchange;
|
exports io.xpipe.beacon.exchange;
|
||||||
exports io.xpipe.beacon.message;
|
|
||||||
exports io.xpipe.beacon.exchange.api;
|
exports io.xpipe.beacon.exchange.api;
|
||||||
exports io.xpipe.beacon.exchange.data;
|
exports io.xpipe.beacon.exchange.data;
|
||||||
exports io.xpipe.beacon.exchange.cli;
|
exports io.xpipe.beacon.exchange.cli;
|
||||||
|
@ -13,7 +12,6 @@ module io.xpipe.beacon {
|
||||||
opens io.xpipe.beacon;
|
opens io.xpipe.beacon;
|
||||||
opens io.xpipe.beacon.exchange;
|
opens io.xpipe.beacon.exchange;
|
||||||
opens io.xpipe.beacon.exchange.api;
|
opens io.xpipe.beacon.exchange.api;
|
||||||
opens io.xpipe.beacon.message;
|
|
||||||
opens io.xpipe.beacon.exchange.data;
|
opens io.xpipe.beacon.exchange.data;
|
||||||
opens io.xpipe.beacon.exchange.cli;
|
opens io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id "org.moditect.gradleplugin" version "1.0.0-rc3"
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "$rootDir/deps/java.gradle"
|
|
||||||
apply from: "$rootDir/deps/commons.gradle"
|
|
||||||
apply from: "$rootDir/deps/junit.gradle"
|
|
||||||
apply from: "$rootDir/deps/lombok.gradle"
|
|
||||||
apply from: "$rootDir/deps/jackson.gradle"
|
|
||||||
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
compileOnly.extendsFrom(dep)
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
module io.xpipe.charsetter {
|
|
||||||
exports io.xpipe.charsetter;
|
|
||||||
|
|
||||||
requires org.apache.commons.io;
|
|
||||||
requires org.apache.commons.lang3;
|
|
||||||
requires static lombok;
|
|
||||||
requires com.fasterxml.jackson.databind;
|
|
||||||
}
|
|
|
@ -2,19 +2,20 @@
|
||||||
[![javadoc](https://javadoc.io/badge2/io.xpipe/core/javadoc.svg)](https://javadoc.io/doc/io.xpipe/core)
|
[![javadoc](https://javadoc.io/badge2/io.xpipe/core/javadoc.svg)](https://javadoc.io/doc/io.xpipe/core)
|
||||||
[![Build Status](https://github.com/xpipe-io/xpipe_java/actions/workflows/core-build.yml/badge.svg)](https://github.com/xpipe-io/xpipe_java/actions/workflows/core-build.yml)
|
[![Build Status](https://github.com/xpipe-io/xpipe_java/actions/workflows/core-build.yml/badge.svg)](https://github.com/xpipe-io/xpipe_java/actions/workflows/core-build.yml)
|
||||||
|
|
||||||
|
|
||||||
## X-Pipe Core
|
## X-Pipe Core
|
||||||
|
|
||||||
The X-Pipe core component contains all the shared core classes used by the API, beacon, and daemon.
|
The X-Pipe core module contains all the shared core classes used by the API, beacon, and daemon implementation.
|
||||||
|
|
||||||
The main part can be found in the [data package]().
|
The main component is the [data package](src/main/java/io/xpipe/core/data).
|
||||||
It contains all definitions of the internal X-Pipe data model and all IO functionality for these data structures.
|
It contains all definitions of the internal X-Pipe data model and all IO functionality for these data structures.
|
||||||
|
|
||||||
The [source package]() contains the basic data source model classes.
|
The [source package](src/main/java/io/xpipe/core/source) contains the basic data source classes,
|
||||||
These have to be used by every custom data source implementation.
|
which are used by every data source implementation.
|
||||||
|
|
||||||
The [store package]() contains the basic data store model classes.
|
The [store package](src/main/java/io/xpipe/core/store) contains the basic data store classes,
|
||||||
These have to be used by every custom data store implementation.
|
which are used by every data store implementation.
|
||||||
|
|
||||||
Every class is expected to be potentially used in the context of files and message exchanges.
|
Every class is expected to be potentially used in the context of files and message exchanges.
|
||||||
As a result, all data structures exchanged must be serializable/deserializable with jackson.
|
As a result, all data structures exchanged must be serializable/deserializable with jackson.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ apply from: "$rootDir/deps/publish-base.gradle"
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
compileOnly.extendsFrom(dep)
|
compileOnly.extendsFrom(dep)
|
||||||
|
testImplementation.extendsFrom(dep)
|
||||||
}
|
}
|
||||||
|
|
||||||
version = file('../version').text
|
version = file('../version').text
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package io.xpipe.charsetter;
|
package io.xpipe.core.charsetter;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
package io.xpipe.charsetter;
|
package io.xpipe.core.charsetter;
|
||||||
|
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.apache.commons.io.ByteOrderMark;
|
|
||||||
import org.apache.commons.io.input.BOMInputStream;
|
|
||||||
import org.apache.commons.lang3.function.FailableConsumer;
|
|
||||||
import org.apache.commons.lang3.function.FailableSupplier;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
@ -15,52 +11,46 @@ import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class Charsetter {
|
public abstract class Charsetter {
|
||||||
|
|
||||||
private static CharsetterUniverse universe;
|
private static CharsetterUniverse universe;
|
||||||
private static final int MAX_BYTES = 8192;
|
|
||||||
|
|
||||||
public static void init(CharsetterContext ctx) {
|
protected static void checkInit() {
|
||||||
universe = CharsetterUniverse.create(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void checkInit() {
|
|
||||||
if (universe == null) {
|
if (universe == null) {
|
||||||
throw new IllegalStateException("Charsetter not initialized");
|
throw new IllegalStateException("Charsetter not initialized");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void init(CharsetterContext ctx) {
|
||||||
|
universe = CharsetterUniverse.create(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
public static class Result {
|
public static class Result {
|
||||||
Charset charset;
|
Charset charset;
|
||||||
NewLine newLine;
|
NewLine newLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Result read(FailableSupplier<InputStream, Exception> in, FailableConsumer<InputStreamReader, Exception> con) throws Exception {
|
public static Charsetter INSTANCE;
|
||||||
checkInit();
|
|
||||||
|
|
||||||
try (var is = in.get();
|
public static Charsetter get() {
|
||||||
var bin = new BOMInputStream(is)) {
|
return INSTANCE;
|
||||||
ByteOrderMark bom = bin.getBOM();
|
|
||||||
String charsetName = bom == null ? null : bom.getCharsetName();
|
|
||||||
var charset = charsetName != null ? Charset.forName(charsetName) : null;
|
|
||||||
|
|
||||||
bin.mark(MAX_BYTES);
|
|
||||||
var bytes = bin.readNBytes(MAX_BYTES);
|
|
||||||
bin.reset();
|
|
||||||
if (charset == null) {
|
|
||||||
charset = inferCharset(bytes);
|
|
||||||
}
|
|
||||||
var nl = inferNewLine(bytes);
|
|
||||||
|
|
||||||
if (con != null) {
|
|
||||||
con.accept(new InputStreamReader(bin, charset));
|
|
||||||
}
|
|
||||||
return new Result(charset, nl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NewLine inferNewLine(byte[] content) {
|
@FunctionalInterface
|
||||||
|
public interface FailableSupplier<R, E extends Throwable> {
|
||||||
|
R get() throws E;
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FailableConsumer<T, E extends Throwable> {
|
||||||
|
|
||||||
|
void accept(T var1) throws E;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Result read(FailableSupplier<InputStream, Exception> in, FailableConsumer<InputStreamReader, Exception> con) throws Exception;
|
||||||
|
|
||||||
|
public NewLine inferNewLine(byte[] content) {
|
||||||
Map<NewLine, Integer> count = new HashMap<>();
|
Map<NewLine, Integer> count = new HashMap<>();
|
||||||
for (var nl : NewLine.values()) {
|
for (var nl : NewLine.values()) {
|
||||||
var nlBytes = nl.getNewLine().getBytes(StandardCharsets.UTF_8);
|
var nlBytes = nl.getNewLine().getBytes(StandardCharsets.UTF_8);
|
||||||
|
@ -75,7 +65,7 @@ public class Charsetter {
|
||||||
.orElseThrow().getKey();
|
.orElseThrow().getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int count(byte[] outerArray, byte[] smallerArray) {
|
private static int count(byte[] outerArray, byte[] smallerArray) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(int i = 0; i < outerArray.length - smallerArray.length+1; ++i) {
|
for(int i = 0; i < outerArray.length - smallerArray.length+1; ++i) {
|
||||||
boolean found = true;
|
boolean found = true;
|
||||||
|
@ -92,7 +82,7 @@ public class Charsetter {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Charset inferCharset(byte[] content) {
|
public Charset inferCharset(byte[] content) {
|
||||||
checkInit();
|
checkInit();
|
||||||
|
|
||||||
for (Charset c : universe.getCharsets()) {
|
for (Charset c : universe.getCharsets()) {
|
|
@ -1,4 +1,4 @@
|
||||||
package io.xpipe.charsetter;
|
package io.xpipe.core.charsetter;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
|
@ -1,4 +1,4 @@
|
||||||
package io.xpipe.charsetter;
|
package io.xpipe.core.charsetter;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
|
@ -1,4 +1,4 @@
|
||||||
package io.xpipe.charsetter;
|
package io.xpipe.core.charsetter;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
|
@ -79,7 +79,13 @@ public class GenericDataStreamParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseValue(InputStream in, GenericDataStreamCallback cb) throws IOException {
|
private static void parseValue(InputStream in, GenericDataStreamCallback cb) throws IOException {
|
||||||
var textual = in.read() != 0;
|
var type = in.read();
|
||||||
|
if (type == DataStructureNodeIO.VALUE_TYPE_NULL) {
|
||||||
|
cb.onValue(null, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var textual = type == DataStructureNodeIO.VALUE_TYPE_TEXT;
|
||||||
var size = in.read();
|
var size = in.read();
|
||||||
var data = in.readNBytes(size);
|
var data = in.readNBytes(size);
|
||||||
cb.onValue(data, textual);
|
cb.onValue(data, textual);
|
||||||
|
|
|
@ -51,10 +51,15 @@ public class GenericDataStreamWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void writeValue(OutputStream out, ValueNode value) throws IOException {
|
private static void writeValue(OutputStream out, ValueNode n) throws IOException {
|
||||||
out.write(DataStructureNodeIO.GENERIC_VALUE_ID);
|
out.write(DataStructureNodeIO.GENERIC_VALUE_ID);
|
||||||
out.write(value.isTextual() ? 1 : 0);
|
if (n.isNull()) {
|
||||||
out.write(value.getRawData().length);
|
out.write(DataStructureNodeIO.VALUE_TYPE_NULL);
|
||||||
out.write(value.getRawData());
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.write(n.isTextual() ? DataStructureNodeIO.VALUE_TYPE_TEXT : DataStructureNodeIO.VALUE_TYPE_BARE);
|
||||||
|
out.write(n.getRawData().length);
|
||||||
|
out.write(n.getRawData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,4 +12,8 @@ public class DataStructureNodeIO {
|
||||||
public static final int TYPED_TUPLE_ID = 6;
|
public static final int TYPED_TUPLE_ID = 6;
|
||||||
public static final int TYPED_ARRAY_ID = 7;
|
public static final int TYPED_ARRAY_ID = 7;
|
||||||
public static final int TYPED_VALUE_ID = 8;
|
public static final int TYPED_VALUE_ID = 8;
|
||||||
|
|
||||||
|
public static final int VALUE_TYPE_BARE = 0;
|
||||||
|
public static final int VALUE_TYPE_TEXT = 1;
|
||||||
|
public static final int VALUE_TYPE_NULL = 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,18 @@ public class MutableValueNode extends ValueNode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(int indent) {
|
public String toString(int indent) {
|
||||||
|
if (isNull()) {
|
||||||
|
return "null (M)";
|
||||||
|
}
|
||||||
|
|
||||||
return (textual ? "\"" : "") + new String(data) + (textual ? "\"" : "") + " (M)";
|
return (textual ? "\"" : "") + new String(data) + (textual ? "\"" : "") + " (M)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNull() {
|
||||||
|
return data == null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTextual() {
|
public boolean isTextual() {
|
||||||
return textual;
|
return textual;
|
||||||
|
|
|
@ -129,7 +129,13 @@ public class TypedDataStreamParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseValue(InputStream in, TypedDataStreamCallback cb) throws IOException {
|
private void parseValue(InputStream in, TypedDataStreamCallback cb) throws IOException {
|
||||||
var textual = in.read() != 0;
|
var type = in.read();
|
||||||
|
if (type == DataStructureNodeIO.VALUE_TYPE_NULL) {
|
||||||
|
cb.onValue(null, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var textual = type == DataStructureNodeIO.VALUE_TYPE_TEXT;
|
||||||
var size = in.read();
|
var size = in.read();
|
||||||
var data = in.readNBytes(size);
|
var data = in.readNBytes(size);
|
||||||
cb.onValue(data, textual);
|
cb.onValue(data, textual);
|
||||||
|
|
|
@ -32,7 +32,12 @@ public class TypedDataStreamWriter {
|
||||||
|
|
||||||
private static void writeValue(OutputStream out, ValueNode n) throws IOException {
|
private static void writeValue(OutputStream out, ValueNode n) throws IOException {
|
||||||
out.write(DataStructureNodeIO.TYPED_VALUE_ID);
|
out.write(DataStructureNodeIO.TYPED_VALUE_ID);
|
||||||
out.write(n.isTextual() ? 1 : 0);
|
if (n.isNull()) {
|
||||||
|
out.write(DataStructureNodeIO.VALUE_TYPE_NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.write(n.isTextual() ? DataStructureNodeIO.VALUE_TYPE_TEXT : DataStructureNodeIO.VALUE_TYPE_BARE);
|
||||||
out.write(n.getRawData().length);
|
out.write(n.getRawData().length);
|
||||||
out.write(n.getRawData());
|
out.write(n.getRawData());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
package io.xpipe.core.dialog;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Value;
|
|
||||||
|
|
||||||
@Value
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class ConfigParameter {
|
|
||||||
String key;
|
|
||||||
|
|
||||||
@JsonCreator
|
|
||||||
public ConfigParameter(String key) {
|
|
||||||
this.key = key;
|
|
||||||
this.converter = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
QueryConverter<?> converter;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T> QueryConverter<T> getConverter() {
|
|
||||||
return (QueryConverter<T>) converter;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
package io.xpipe.core.dialog;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Value;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Value
|
|
||||||
@AllArgsConstructor(onConstructor_={@JsonCreator})
|
|
||||||
public class ConfigParameterSetInstance {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The available configuration parameters.
|
|
||||||
*/
|
|
||||||
List<ConfigParameter> configParameters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current configuration options that are set.
|
|
||||||
*/
|
|
||||||
Map<String, String> currentValues;
|
|
||||||
|
|
||||||
public ConfigParameterSetInstance(Map<ConfigParameter, Object> map) {
|
|
||||||
configParameters = map.keySet().stream().toList();
|
|
||||||
currentValues = map.entrySet().stream().collect(Collectors.toMap(
|
|
||||||
e -> e.getKey().getKey(),
|
|
||||||
e -> e.getKey().getConverter().convertToString(e.getValue())));
|
|
||||||
}
|
|
||||||
|
|
||||||
public <X, T extends Function<X,?>> ConfigParameterSetInstance(Map<ConfigParameter, T> map, Object v) {
|
|
||||||
configParameters = map.keySet().stream().toList();
|
|
||||||
currentValues = map.entrySet().stream().collect(Collectors.toMap(
|
|
||||||
e -> e.getKey().getKey(),
|
|
||||||
e -> e.getKey().getConverter().convertToString(apply(e.getValue(), v))));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static <X, T extends Function<X,?>, V> Object apply(T func, Object v) {
|
|
||||||
return func.apply((X) v);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(ConfigParameter p, String val) {
|
|
||||||
currentValues.put(p.getKey(), val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<ConfigParameter, Object> evaluate() {
|
|
||||||
return configParameters.stream().collect(Collectors.toMap(
|
|
||||||
p -> p,
|
|
||||||
p -> p.getConverter().convertFromString(currentValues.get(p.getKey()))));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package io.xpipe.core.source;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import io.xpipe.core.dialog.ConfigParameter;
|
|
||||||
import io.xpipe.core.dialog.ConfigParameterSetInstance;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Value;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the current configuration of a data source.
|
|
||||||
* This configuration can either be in progress or complete.
|
|
||||||
*/
|
|
||||||
@Value
|
|
||||||
@AllArgsConstructor(onConstructor_={@JsonCreator})
|
|
||||||
public class DataSourceConfigInstance {
|
|
||||||
|
|
||||||
public static DataSourceConfigInstance xpbt() {
|
|
||||||
return new DataSourceConfigInstance("xpbt", new ConfigParameterSetInstance(Map.of()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The data source provider id.
|
|
||||||
*/
|
|
||||||
String provider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The available configuration parameters.
|
|
||||||
*/
|
|
||||||
ConfigParameterSetInstance configInstance;
|
|
||||||
|
|
||||||
public DataSourceConfigInstance(String provider, Map<ConfigParameter, Object> map) {
|
|
||||||
this.provider = provider;
|
|
||||||
this.configInstance = new ConfigParameterSetInstance(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <X, T extends Function<X,?>> DataSourceConfigInstance(String provider, Map<ConfigParameter, T> map, Object val) {
|
|
||||||
this.provider = provider;
|
|
||||||
this.configInstance = new ConfigParameterSetInstance(map, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<ConfigParameter, Object> evaluate() {
|
|
||||||
return configInstance.evaluate();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,7 +9,6 @@ module io.xpipe.core {
|
||||||
exports io.xpipe.core.data.node;
|
exports io.xpipe.core.data.node;
|
||||||
exports io.xpipe.core.data.typed;
|
exports io.xpipe.core.data.typed;
|
||||||
exports io.xpipe.core.dialog;
|
exports io.xpipe.core.dialog;
|
||||||
exports io.xpipe.core.connection;
|
|
||||||
|
|
||||||
opens io.xpipe.core.store;
|
opens io.xpipe.core.store;
|
||||||
opens io.xpipe.core.source;
|
opens io.xpipe.core.source;
|
||||||
|
@ -19,6 +18,7 @@ module io.xpipe.core {
|
||||||
opens io.xpipe.core.data.node;
|
opens io.xpipe.core.data.node;
|
||||||
opens io.xpipe.core.data.typed;
|
opens io.xpipe.core.data.typed;
|
||||||
opens io.xpipe.core.dialog;
|
opens io.xpipe.core.dialog;
|
||||||
|
exports io.xpipe.core.charsetter;
|
||||||
|
|
||||||
requires com.fasterxml.jackson.core;
|
requires com.fasterxml.jackson.core;
|
||||||
requires com.fasterxml.jackson.databind;
|
requires com.fasterxml.jackson.databind;
|
||||||
|
|
|
@ -5,16 +5,14 @@
|
||||||
## X-Pipe Extension API
|
## X-Pipe Extension API
|
||||||
|
|
||||||
The X-Pipe extension API allows you to create extensions of any kind for X-Pipe.
|
The X-Pipe extension API allows you to create extensions of any kind for X-Pipe.
|
||||||
|
This includes:
|
||||||
|
- Custom data stores, including configuration GUI and CLI
|
||||||
|
- Custom data sources, including configuration GUI and CLI
|
||||||
|
- Custom preferences entries
|
||||||
|
|
||||||
### Custom data sources
|
### Custom data sources
|
||||||
|
|
||||||
A custom data source type can be implemented by creating a custom [DataSourceProvider]().
|
A custom data source type can be implemented by creating a custom
|
||||||
|
[DataSourceProvider](src/main/java/io/xpipe/extension/DataSourceProvider.java).
|
||||||
This provider contains all the information required for proper handling of your custom data sources,
|
This provider contains all the information required for proper handling of your custom data sources,
|
||||||
whether you access it from the CLI, any API, or the X-Pipe commander gui.
|
whether you access it from the CLI, any API, or the X-Pipe commander gui.
|
||||||
|
|
||||||
### Custom data sinks
|
|
||||||
|
|
||||||
A custom data sink type can be implemented by creating a custom [DataSinkProvider]().
|
|
||||||
As the notion of a sink is abstract, it allows you to basically implement any type of sink you want.
|
|
||||||
Whether the target is a programming language, another application, a database, or a regular file.
|
|
|
@ -32,7 +32,6 @@ repositories {
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly 'org.junit.jupiter:junit-jupiter-api:5.8.2'
|
compileOnly 'org.junit.jupiter:junit-jupiter-api:5.8.2'
|
||||||
implementation project(':core')
|
implementation project(':core')
|
||||||
implementation project(':charsetter')
|
|
||||||
|
|
||||||
implementation 'io.xpipe:fxcomps:0.1'
|
implementation 'io.xpipe:fxcomps:0.1'
|
||||||
implementation 'com.google.code.gson:gson:2.9.0'
|
implementation 'com.google.code.gson:gson:2.9.0'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package io.xpipe.extension;
|
package io.xpipe.extension;
|
||||||
|
|
||||||
import io.xpipe.charsetter.NewLine;
|
import io.xpipe.core.charsetter.NewLine;
|
||||||
import io.xpipe.core.dialog.Dialog;
|
import io.xpipe.core.dialog.Dialog;
|
||||||
import io.xpipe.core.dialog.QueryConverter;
|
import io.xpipe.core.dialog.QueryConverter;
|
||||||
import io.xpipe.core.source.DataSource;
|
import io.xpipe.core.source.DataSource;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package io.xpipe.extension;
|
package io.xpipe.extension;
|
||||||
|
|
||||||
import io.xpipe.charsetter.Charsetter;
|
import io.xpipe.core.charsetter.Charsetter;
|
||||||
import io.xpipe.charsetter.CharsetterContext;
|
import io.xpipe.core.charsetter.CharsetterContext;
|
||||||
import io.xpipe.core.util.JacksonHelper;
|
import io.xpipe.core.util.JacksonHelper;
|
||||||
import io.xpipe.extension.util.ModuleHelper;
|
import io.xpipe.extension.util.ModuleHelper;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package io.xpipe.extension.comp;
|
package io.xpipe.extension.comp;
|
||||||
|
|
||||||
import io.xpipe.charsetter.NewLine;
|
import io.xpipe.core.charsetter.NewLine;
|
||||||
import io.xpipe.core.source.DataSource;
|
import io.xpipe.core.source.DataSource;
|
||||||
import io.xpipe.extension.I18n;
|
import io.xpipe.extension.I18n;
|
||||||
import io.xpipe.fxcomps.Comp;
|
import io.xpipe.fxcomps.Comp;
|
||||||
|
|
|
@ -28,7 +28,6 @@ module io.xpipe.extension {
|
||||||
requires org.kordamp.ikonli.javafx;
|
requires org.kordamp.ikonli.javafx;
|
||||||
requires com.fasterxml.jackson.databind;
|
requires com.fasterxml.jackson.databind;
|
||||||
requires static org.junit.jupiter.api;
|
requires static org.junit.jupiter.api;
|
||||||
requires io.xpipe.charsetter;
|
|
||||||
|
|
||||||
uses DataSourceProvider;
|
uses DataSourceProvider;
|
||||||
uses SupportedApplicationProvider;
|
uses SupportedApplicationProvider;
|
||||||
|
|
100
jreleaser.gradle
Normal file
100
jreleaser.gradle
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
def isPreRelease = project.version.endsWith('-pre')
|
||||||
|
def isFullRelease = !isPreRelease && !project.version.endsWith('-SNAPSHOT')
|
||||||
|
def proj = project
|
||||||
|
def canonicalVersion = file('canonical_version').text
|
||||||
|
|
||||||
|
jreleaser {
|
||||||
|
environment {
|
||||||
|
properties.put('rawChangelog', file("changelogs/${canonicalVersion}.txt").exists() ?
|
||||||
|
file("changelogs/${canonicalVersion}.txt").text.replace('\r\n', '\n') : "")
|
||||||
|
}
|
||||||
|
|
||||||
|
project {
|
||||||
|
name = 'Pdx-Unlimiter'
|
||||||
|
description = 'A smart savegame manager, editor, and toolbox for all current major Paradox Grand Strategy games.'
|
||||||
|
longDescription = 'The Pdx-Unlimiter is a tool for all major Paradox Grand Strategy games that provides a ' +
|
||||||
|
'powerful and smart savegame manager to quickly organize and play all of your savegames with ease. ' +
|
||||||
|
'Furthermore, it also comes with an Ironman converter, a powerful savegame editor, some savescumming ' +
|
||||||
|
'tools, integrations for various other great community-made tools for all major Paradox games.'
|
||||||
|
website = 'https://github.com/crschnick/pdx_unlimiter'
|
||||||
|
authors = ['Christopher Schnick']
|
||||||
|
license = 'GPL3'
|
||||||
|
copyright = ' '
|
||||||
|
|
||||||
|
java {
|
||||||
|
groupId = 'com.crschnick.pdxu'
|
||||||
|
version = '17'
|
||||||
|
multiProject = true
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot {
|
||||||
|
enabled = true
|
||||||
|
pattern = '.*-SNAPSHOT'
|
||||||
|
label = 'early-access'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
release {
|
||||||
|
github {
|
||||||
|
skipRelease = !isFullRelease && !isPreRelease
|
||||||
|
skipTag = !isFullRelease && !isPreRelease
|
||||||
|
owner = 'crschnick'
|
||||||
|
overwrite = false
|
||||||
|
tagName = '{{projectVersion}}'
|
||||||
|
releaseName = '{{tagName}}'
|
||||||
|
token = proj.hasProperty("PDXU_GITHUB_TOKEN") ? proj.property("PDXU_GITHUB_TOKEN") : System.getenv("JRELEASER_GITHUB_TOKEN")
|
||||||
|
|
||||||
|
files = true
|
||||||
|
artifacts = true
|
||||||
|
checksums = false
|
||||||
|
signatures = false
|
||||||
|
|
||||||
|
// Always set a pre-release, as drafts do not fully work
|
||||||
|
prerelease {
|
||||||
|
enabled = true
|
||||||
|
pattern = '.*'
|
||||||
|
}
|
||||||
|
|
||||||
|
update {
|
||||||
|
enabled = true
|
||||||
|
section('ASSETS')
|
||||||
|
section('TITLE')
|
||||||
|
section('BODY')
|
||||||
|
}
|
||||||
|
|
||||||
|
changelog {
|
||||||
|
enabled = true
|
||||||
|
formatted = 'ALWAYS'
|
||||||
|
contentTemplate = isFullRelease ? file('misc/github_full.tpl') : file('misc/github_pre.tpl')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
distributions {
|
||||||
|
app {
|
||||||
|
if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {
|
||||||
|
artifact {
|
||||||
|
distributionType = 'BINARY'
|
||||||
|
path = 'build/pdx_unlimiter-windows.zip'
|
||||||
|
platform = 'windows'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
artifact {
|
||||||
|
distributionType = 'BINARY'
|
||||||
|
path = 'build/pdx_unlimiter-linux.zip'
|
||||||
|
platform = 'linux'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
announce {
|
||||||
|
enabled = isFullRelease || isPreRelease
|
||||||
|
discord {
|
||||||
|
active = 'ALWAYS'
|
||||||
|
|
||||||
|
webhook = proj.hasProperty("PDXU_DISCORD_WEBHOOK") ? proj.property("PDXU_DISCORD_WEBHOOK") : System.getenv("JRELEASER_DISCORD_WEBHOOK")
|
||||||
|
|
||||||
|
messageTemplate = isFullRelease ? 'misc/discord_full.tpl' : 'misc/discord_pre.tpl'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue