mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-09-28 23:31:43 +12:00
Cleanup, some documentation, and refactoring
This commit is contained in:
parent
f5cccd5687
commit
f7b37412b4
49 changed files with 234 additions and 270 deletions
|
@ -24,11 +24,6 @@ dependencies {
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
|
||||||
testLogging {
|
|
||||||
exceptionFormat = 'full'
|
|
||||||
showStandardStreams = true
|
|
||||||
}
|
|
||||||
workingDir = rootDir
|
workingDir = rootDir
|
||||||
|
|
||||||
// Daemon properties
|
// Daemon properties
|
||||||
|
@ -38,10 +33,11 @@ test {
|
||||||
" -Dio.xpipe.app.dataDir=$projectDir/local/" +
|
" -Dio.xpipe.app.dataDir=$projectDir/local/" +
|
||||||
" -Dio.xpipe.storage.persist=false" +
|
" -Dio.xpipe.storage.persist=false" +
|
||||||
" -Dio.xpipe.app.writeSysOut=true" +
|
" -Dio.xpipe.app.writeSysOut=true" +
|
||||||
" -Dio.xpipe.beacon.debugOutput=true" +
|
// " -Dio.xpipe.beacon.debugOutput=true" +
|
||||||
" -Dio.xpipe.app.logLevel=trace"
|
" -Dio.xpipe.app.logLevel=trace"
|
||||||
|
|
||||||
// API properties
|
// API properties
|
||||||
// systemProperty 'io.xpipe.beacon.debugOutput', "true"
|
// systemProperty 'io.xpipe.beacon.debugOutput', "true"
|
||||||
|
systemProperty 'io.xpipe.beacon.debugExecOutput', "true"
|
||||||
systemProperty "io.xpipe.beacon.port", "21722"
|
systemProperty "io.xpipe.beacon.port", "21722"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ publishing {
|
||||||
from components.java
|
from components.java
|
||||||
|
|
||||||
pom {
|
pom {
|
||||||
name = 'X-Pipe API'
|
name = 'X-Pipe Java API'
|
||||||
description = 'Contains everything necessary to use and interact with X-Pipe.'
|
description = 'Contains everything necessary to interact with X-Pipe from Java applications.'
|
||||||
url = 'https://github.com/xpipe-io/xpipe_java/api'
|
url = 'https://github.com/xpipe-io/xpipe_java/api'
|
||||||
licenses {
|
licenses {
|
||||||
license {
|
license {
|
||||||
|
@ -25,10 +25,6 @@ publishing {
|
||||||
developerConnection = 'scm:git:ssh://github.com/xpipe-io/xpipe_java.git'
|
developerConnection = 'scm:git:ssh://github.com/xpipe-io/xpipe_java.git'
|
||||||
url = 'https://github.com/xpipe-io/xpipe_java'
|
url = 'https://github.com/xpipe-io/xpipe_java'
|
||||||
}
|
}
|
||||||
|
|
||||||
withXml {
|
|
||||||
//asNode().appendNode('dependencies').appendNode('dependency').appendNode('my-property', 'my-value')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package io.xpipe.api;
|
||||||
import io.xpipe.api.impl.DataTableAccumulatorImpl;
|
import io.xpipe.api.impl.DataTableAccumulatorImpl;
|
||||||
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.type.TupleType;
|
import io.xpipe.core.data.type.TupleType;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
|
|
||||||
|
@ -11,7 +10,7 @@ import io.xpipe.core.source.DataSourceId;
|
||||||
* An accumulator for table data.
|
* An accumulator for table data.
|
||||||
*
|
*
|
||||||
* This class can be used to construct new table data sources by
|
* This class can be used to construct new table data sources by
|
||||||
* accumulating the rows using {@link #add(TupleNode)} or {@link #acceptor()} and then calling
|
* accumulating the rows using {@link #add(DataStructureNode)} or {@link #acceptor()} and then calling
|
||||||
* {@link #finish(DataSourceId)} to complete the construction process and create a new data source.
|
* {@link #finish(DataSourceId)} to complete the construction process and create a new data source.
|
||||||
*/
|
*/
|
||||||
public interface DataTableAccumulator {
|
public interface DataTableAccumulator {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package io.xpipe.api.impl;
|
||||||
|
|
||||||
import io.xpipe.api.DataSource;
|
import io.xpipe.api.DataSource;
|
||||||
import io.xpipe.api.connector.XPipeConnection;
|
import io.xpipe.api.connector.XPipeConnection;
|
||||||
import io.xpipe.beacon.exchange.PreStoreExchange;
|
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.ReadExecuteExchange;
|
||||||
import io.xpipe.beacon.exchange.ReadPreparationExchange;
|
import io.xpipe.beacon.exchange.ReadPreparationExchange;
|
||||||
|
@ -43,8 +43,8 @@ public abstract class DataSourceImpl implements DataSource {
|
||||||
|
|
||||||
public static DataSource create(DataSourceId id, String type, Map<String,String> config, InputStream in) {
|
public static DataSource create(DataSourceId id, String type, Map<String,String> config, InputStream in) {
|
||||||
var res = XPipeConnection.execute(con -> {
|
var res = XPipeConnection.execute(con -> {
|
||||||
var req = PreStoreExchange.Request.builder().build();
|
var req = StoreStreamExchange.Request.builder().build();
|
||||||
PreStoreExchange.Response r = con.performOutputExchange(req, out -> in.transferTo(out));
|
StoreStreamExchange.Response r = con.performOutputExchange(req, out -> in.transferTo(out));
|
||||||
return r;
|
return r;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ 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.PreStoreExchange;
|
import io.xpipe.beacon.exchange.StoreStreamExchange;
|
||||||
import io.xpipe.beacon.exchange.ReadExecuteExchange;
|
import io.xpipe.beacon.exchange.ReadExecuteExchange;
|
||||||
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;
|
||||||
|
@ -29,14 +29,14 @@ public class DataTableAccumulatorImpl implements DataTableAccumulator {
|
||||||
public DataTableAccumulatorImpl(TupleType type) {
|
public DataTableAccumulatorImpl(TupleType type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
connection = XPipeConnection.open();
|
connection = XPipeConnection.open();
|
||||||
connection.sendRequest(PreStoreExchange.Request.builder().build());
|
connection.sendRequest(StoreStreamExchange.Request.builder().build());
|
||||||
connection.sendBody();
|
connection.sendBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized DataTable finish(DataSourceId id) {
|
public synchronized DataTable finish(DataSourceId id) {
|
||||||
connection.withOutputStream(OutputStream::close);
|
connection.withOutputStream(OutputStream::close);
|
||||||
PreStoreExchange.Response res = connection.receiveResponse();
|
StoreStreamExchange.Response res = connection.receiveResponse();
|
||||||
connection.close();
|
connection.close();
|
||||||
|
|
||||||
var req = ReadExecuteExchange.Request.builder()
|
var req = ReadExecuteExchange.Request.builder()
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
module io.xpipe.api {
|
module io.xpipe.api {
|
||||||
|
exports io.xpipe.api;
|
||||||
|
|
||||||
requires transitive io.xpipe.core;
|
requires transitive io.xpipe.core;
|
||||||
requires io.xpipe.beacon;
|
requires io.xpipe.beacon;
|
||||||
|
|
||||||
exports io.xpipe.api;
|
|
||||||
exports io.xpipe.api.connector;
|
|
||||||
}
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
cd ..\app\
|
|
||||||
SET "dir=%~dp0test_env"
|
|
||||||
CALL ..\gradlew.bat run -Dio.xpipe.storage.dir=%dir% -Dio.xpipe.beacon.port=21722 -Dio.xpipe.daemon.mode=gui
|
|
||||||
pause
|
|
36
beacon/README.md
Normal file
36
beacon/README.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
## X-Pipe Beacon
|
||||||
|
|
||||||
|
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
|
||||||
|
of different operations.
|
||||||
|
The underlying inter-process communication is realized through TCP sockets on port `21721`.
|
||||||
|
|
||||||
|
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.
|
||||||
|
The daemon then always sends a response message.
|
||||||
|
|
||||||
|
The header information of a message is formatted in the json format.
|
||||||
|
As a result, all data structures exchanged must be serializable/deserializable with jackson.
|
||||||
|
|
||||||
|
Both the requests and responses can optionally include content in a body.
|
||||||
|
A body is initiated with two new lines (`\n`).
|
||||||
|
The body is split into segments of max length `65536`.
|
||||||
|
Each segment is preceded by four bytes that specify the length of the next segment.
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The beacon API also supports launching the daemon automatically in case it is not started yet.
|
||||||
|
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>`.
|
||||||
|
This allows for a custom launch behaviour in a testing/development environment.
|
||||||
|
|
||||||
|
By passing the property `io.xpipe.beacon.debugOutput=true`, it is possible to print debug information
|
||||||
|
about the underlying communications.
|
||||||
|
In case the `io.xpipe.beacon.exec` property is set, the output of the custom exec command can also be
|
||||||
|
printed by passing the property `io.xpipe.beacon.debugExecOutput=true`.
|
||||||
|
|
|
@ -4,8 +4,8 @@ publishing {
|
||||||
from components.java
|
from components.java
|
||||||
|
|
||||||
pom {
|
pom {
|
||||||
name = 'X-Pipe beacon'
|
name = 'X-Pipe Beacon'
|
||||||
description = 'The socket-based implementation used for the communication with X-Pipe.'
|
description = 'The socket-based implementation used for the communication with the X-Pipe daemon.'
|
||||||
url = 'https://github.com/xpipe-io/xpipe_java/beacon'
|
url = 'https://github.com/xpipe-io/xpipe_java/beacon'
|
||||||
licenses {
|
licenses {
|
||||||
license {
|
license {
|
||||||
|
|
|
@ -68,10 +68,6 @@ public class BeaconClient implements AutoCloseable {
|
||||||
out = socket.getOutputStream();
|
out = socket.getOutputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isClosed() {
|
|
||||||
return socket.isClosed();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() throws ConnectorException {
|
public void close() throws ConnectorException {
|
||||||
try {
|
try {
|
||||||
socket.close();
|
socket.close();
|
||||||
|
@ -132,14 +128,14 @@ public class BeaconClient implements AutoCloseable {
|
||||||
throw new ClientException("Unknown request class " + req.getClass());
|
throw new ClientException("Unknown request class " + req.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
json.set("type", new TextNode(prov.get().getId()));
|
json.set("messageType", new TextNode(prov.get().getId()));
|
||||||
json.set("phase", new TextNode("request"));
|
json.set("messagePhase", new TextNode("request"));
|
||||||
//json.set("id", new TextNode(UUID.randomUUID().toString()));
|
//json.set("id", new TextNode(UUID.randomUUID().toString()));
|
||||||
var msg = JsonNodeFactory.instance.objectNode();
|
var msg = JsonNodeFactory.instance.objectNode();
|
||||||
msg.set("xPipeMessage", json);
|
msg.set("xPipeMessage", json);
|
||||||
|
|
||||||
if (BeaconConfig.debugEnabled()) {
|
if (BeaconConfig.debugEnabled()) {
|
||||||
System.out.println("Sending request to server of type " + req.getClass().getSimpleName());
|
System.out.println("Sending request to server of type " + req.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -163,7 +159,7 @@ public class BeaconClient implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BeaconConfig.debugEnabled()) {
|
if (BeaconConfig.debugEnabled()) {
|
||||||
System.out.println("Recieved response:");
|
System.out.println("Received response:");
|
||||||
System.out.println(read.toPrettyString());
|
System.out.println(read.toPrettyString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,14 +207,14 @@ public class BeaconClient implements AutoCloseable {
|
||||||
private <T extends ResponseMessage> T parseResponse(JsonNode header) throws ConnectorException {
|
private <T extends ResponseMessage> T parseResponse(JsonNode header) throws ConnectorException {
|
||||||
ObjectNode content = (ObjectNode) header.required("xPipeMessage");
|
ObjectNode content = (ObjectNode) header.required("xPipeMessage");
|
||||||
|
|
||||||
var type = content.required("type").textValue();
|
var type = content.required("messageType").textValue();
|
||||||
var phase = content.required("phase").textValue();
|
var phase = content.required("messagePhase").textValue();
|
||||||
//var requestId = UUID.fromString(content.required("id").textValue());
|
//var requestId = UUID.fromString(content.required("id").textValue());
|
||||||
if (!phase.equals("response")) {
|
if (!phase.equals("response")) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
content.remove("type");
|
content.remove("messageType");
|
||||||
content.remove("phase");
|
content.remove("messagePhase");
|
||||||
//content.remove("id");
|
//content.remove("id");
|
||||||
|
|
||||||
var prov = MessageExchanges.byId(type);
|
var prov = MessageExchanges.byId(type);
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
public class BeaconConfig {
|
public class BeaconConfig {
|
||||||
|
|
||||||
public static final byte[] BODY_SEPARATOR = "\n\n".getBytes(StandardCharsets.UTF_8);
|
public static final byte[] BODY_SEPARATOR = "\n\n".getBytes(StandardCharsets.UTF_8);
|
||||||
|
@ -15,6 +18,16 @@ public class BeaconConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final String EXEC_DEBUG_PROP = "io.xpipe.beacon.debugExecOutput";
|
||||||
|
|
||||||
|
public static boolean execDebugEnabled() {
|
||||||
|
if (System.getProperty(EXEC_DEBUG_PROP) != null) {
|
||||||
|
return Boolean.parseBoolean(System.getProperty(EXEC_DEBUG_PROP));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static final String BEACON_PORT_PROP = "io.xpipe.beacon.port";
|
public static final String BEACON_PORT_PROP = "io.xpipe.beacon.port";
|
||||||
public static final int DEFAULT_PORT = 21721;
|
public static final int DEFAULT_PORT = 21721;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An unchecked exception that will be thrown in any case of an underlying exception.
|
||||||
|
*/
|
||||||
public class BeaconException extends RuntimeException {
|
public class BeaconException extends RuntimeException {
|
||||||
|
|
||||||
public BeaconException() {
|
public BeaconException() {
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
public class BeaconFormat {
|
public class BeaconFormat {
|
||||||
|
|
||||||
|
private static final int SEGMENT_SIZE = 65536;
|
||||||
|
|
||||||
public static OutputStream writeBlocks(Socket socket) throws IOException {
|
public static OutputStream writeBlocks(Socket socket) throws IOException {
|
||||||
int size = 65536 - 4;
|
|
||||||
var out = socket.getOutputStream();
|
var out = socket.getOutputStream();
|
||||||
return new OutputStream() {
|
return new OutputStream() {
|
||||||
private final byte[] currentBytes = new byte[size];
|
private final byte[] currentBytes = new byte[SEGMENT_SIZE];
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,21 +47,9 @@ public class BeaconFormat {
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// while (true) {
|
|
||||||
// var bytes = in.readNBytes(size);
|
|
||||||
// int length = bytes.length;
|
|
||||||
// var lengthBuffer = ByteBuffer.allocate(4).putInt(length);
|
|
||||||
// socket.getOutputStream().write(lengthBuffer.array());
|
|
||||||
// socket.getOutputStream().write(bytes);
|
|
||||||
//
|
|
||||||
// if (length == 0) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static InputStream readBlocks(Socket socket) throws IOException {
|
public static InputStream readBlocks(Socket socket) throws IOException {
|
||||||
int size = 65536 - 4;
|
|
||||||
var in = socket.getInputStream();
|
var in = socket.getInputStream();
|
||||||
return new InputStream() {
|
return new InputStream() {
|
||||||
|
|
||||||
|
@ -90,7 +82,7 @@ public class BeaconFormat {
|
||||||
|
|
||||||
currentBytes = in.readNBytes(lengthInt);
|
currentBytes = in.readNBytes(lengthInt);
|
||||||
index = 0;
|
index = 0;
|
||||||
if (lengthInt < size) {
|
if (lengthInt < SEGMENT_SIZE) {
|
||||||
finished = true;
|
finished = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,29 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exchange handler responsible for properly handling a request and sending a response.
|
||||||
|
*/
|
||||||
public interface BeaconHandler {
|
public interface BeaconHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a Runnable after the initial response has been sent.
|
||||||
|
*
|
||||||
|
* @param r the runnable to execute
|
||||||
|
*/
|
||||||
void postResponse(BeaconClient.FailableRunnable<Exception> r);
|
void postResponse(BeaconClient.FailableRunnable<Exception> r);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares to attach a body to a response.
|
||||||
|
*
|
||||||
|
* @return the output stream that can be used to write the body payload
|
||||||
|
*/
|
||||||
OutputStream sendBody() throws IOException;
|
OutputStream sendBody() throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares to read an attached body of a request.
|
||||||
|
*
|
||||||
|
* @return the input stream that can be used to read the body payload
|
||||||
|
*/
|
||||||
InputStream receiveBody() throws IOException;
|
InputStream receiveBody() throws IOException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.StopExchange;
|
import io.xpipe.beacon.exchange.StopExchange;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -11,10 +12,14 @@ import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains basic functionality to start, communicate, and stop a beacon server.
|
||||||
|
*/
|
||||||
|
@UtilityClass
|
||||||
public class BeaconServer {
|
public class BeaconServer {
|
||||||
|
|
||||||
private static boolean isPortAvailable(int port) {
|
private static boolean isPortAvailable(int port) {
|
||||||
try (var ss = new ServerSocket(port); var ds = new DatagramSocket(port)) {
|
try (var ignored = new ServerSocket(port); var ignored1 = new DatagramSocket(port)) {
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -27,15 +32,18 @@ public class BeaconServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startFork(String custom) throws IOException {
|
private static void startFork(String custom) throws IOException {
|
||||||
boolean print = true;
|
boolean print = BeaconConfig.execDebugEnabled();
|
||||||
var proc = Runtime.getRuntime().exec(custom);
|
var proc = Runtime.getRuntime().exec(custom);
|
||||||
new Thread(null, () -> {
|
new Thread(null, () -> {
|
||||||
try {
|
try {
|
||||||
InputStreamReader isr = new InputStreamReader(proc.getInputStream());
|
InputStreamReader isr = new InputStreamReader(proc.getInputStream());
|
||||||
BufferedReader br = new BufferedReader(isr);
|
BufferedReader br = new BufferedReader(isr);
|
||||||
String line = null;
|
String line;
|
||||||
while ((line = br.readLine()) != null)
|
while ((line = br.readLine()) != null) {
|
||||||
System.out.println("[xpiped] " + line);
|
if (print) {
|
||||||
|
System.out.println("[xpiped] " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -70,7 +78,7 @@ public class BeaconServer {
|
||||||
|
|
||||||
private static Optional<Path> getPortableLauncherExecutable() {
|
private static Optional<Path> getPortableLauncherExecutable() {
|
||||||
var env = System.getenv("XPIPE_HOME");
|
var env = System.getenv("XPIPE_HOME");
|
||||||
Path file = null;
|
Path file;
|
||||||
|
|
||||||
// Prepare for invalid XPIPE_HOME path value
|
// Prepare for invalid XPIPE_HOME path value
|
||||||
try {
|
try {
|
||||||
|
@ -92,7 +100,7 @@ public class BeaconServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Path file = null;
|
Path file;
|
||||||
if (System.getProperty("os.name").startsWith("Windows")) {
|
if (System.getProperty("os.name").startsWith("Windows")) {
|
||||||
file = Path.of(System.getenv("LOCALAPPDATA"), "X-Pipe", "xpipe_launcher.exe");
|
file = Path.of(System.getenv("LOCALAPPDATA"), "X-Pipe", "xpipe_launcher.exe");
|
||||||
} else {
|
} else {
|
||||||
|
@ -106,7 +114,7 @@ public class BeaconServer {
|
||||||
|
|
||||||
public static Optional<Path> getDaemonExecutable() {
|
public static Optional<Path> getDaemonExecutable() {
|
||||||
try {
|
try {
|
||||||
Path file = null;
|
Path file;
|
||||||
if (System.getProperty("os.name").startsWith("Windows")) {
|
if (System.getProperty("os.name").startsWith("Windows")) {
|
||||||
file = Path.of(System.getenv("LOCALAPPDATA"), "X-Pipe", "app", "xpipe.exe");
|
file = Path.of(System.getenv("LOCALAPPDATA"), "X-Pipe", "app", "xpipe.exe");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that a client request caused an issue.
|
||||||
|
*/
|
||||||
public class ClientException extends Exception {
|
public class ClientException extends Exception {
|
||||||
|
|
||||||
public ClientException() {
|
public ClientException() {
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that a connection error occurred.
|
||||||
|
*/
|
||||||
public class ConnectorException extends Exception {
|
public class ConnectorException extends Exception {
|
||||||
|
|
||||||
public ConnectorException() {
|
public ConnectorException() {
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
|
import lombok.experimental.StandardException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that an internal server error occurred.
|
||||||
|
*/
|
||||||
|
@StandardException
|
||||||
public class ServerException extends Exception {
|
public class ServerException extends Exception {
|
||||||
|
|
||||||
public ServerException() {
|
public ServerException() {
|
||||||
|
|
|
@ -9,6 +9,9 @@ import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs an edit for a data source.
|
||||||
|
*/
|
||||||
public class EditExecuteExchange implements MessageExchange<EditExecuteExchange.Request, EditExecuteExchange.Response> {
|
public class EditExecuteExchange implements MessageExchange<EditExecuteExchange.Request, EditExecuteExchange.Response> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -9,6 +9,9 @@ import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests to edit a data source.
|
||||||
|
*/
|
||||||
public class EditPreparationExchange implements MessageExchange<EditPreparationExchange.Request, EditPreparationExchange.Response> {
|
public class EditPreparationExchange implements MessageExchange<EditPreparationExchange.Request, EditPreparationExchange.Response> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,12 +2,30 @@ package io.xpipe.beacon.exchange;
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message exchange scheme that implements a certain functionality.
|
||||||
|
*/
|
||||||
public interface MessageExchange<RQ extends RequestMessage, RP extends ResponseMessage> {
|
public interface MessageExchange<RQ extends RequestMessage, RP extends ResponseMessage> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The unique id of this exchange that will be included in the messages.
|
||||||
|
*/
|
||||||
String getId();
|
String getId();
|
||||||
|
|
||||||
Class<RQ> getRequestClass();
|
/**
|
||||||
|
* Returns the request class, needed for serialization.
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
default Class<RQ> getRequestClass() {
|
||||||
|
var name = getClass().getName() + "$Request";
|
||||||
|
return (Class<RQ>) Class.forName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the response class, needed for serialization.
|
||||||
|
*/
|
||||||
Class<RP> getResponseClass();
|
Class<RP> getResponseClass();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
package io.xpipe.beacon.exchange;
|
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
|
||||||
import io.xpipe.core.store.StreamDataStore;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Value;
|
|
||||||
import lombok.extern.jackson.Jacksonized;
|
|
||||||
|
|
||||||
public class PreStoreExchange implements MessageExchange<PreStoreExchange.Request, PreStoreExchange.Response> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return "preStore";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<PreStoreExchange.Request> getRequestClass() {
|
|
||||||
return PreStoreExchange.Request.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<PreStoreExchange.Response> getResponseClass() {
|
|
||||||
return PreStoreExchange.Response.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
|
||||||
@Builder
|
|
||||||
@Value
|
|
||||||
public static class Request implements RequestMessage {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
|
||||||
@Builder
|
|
||||||
@Value
|
|
||||||
public static class Response implements ResponseMessage {
|
|
||||||
StreamDataStore store;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,6 +9,9 @@ import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries general information about a data source.
|
||||||
|
*/
|
||||||
public class QueryDataSourceExchange implements MessageExchange<QueryDataSourceExchange.Request, QueryDataSourceExchange.Response> {
|
public class QueryDataSourceExchange implements MessageExchange<QueryDataSourceExchange.Request, QueryDataSourceExchange.Response> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -10,6 +10,9 @@ import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends stream-based data to a daemon.
|
||||||
|
*/
|
||||||
public class ReadExecuteExchange implements MessageExchange<ReadExecuteExchange.Request, ReadExecuteExchange.Response> {
|
public class ReadExecuteExchange implements MessageExchange<ReadExecuteExchange.Request, ReadExecuteExchange.Response> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -9,6 +9,9 @@ import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares a client to send stream-based data to a daemon.
|
||||||
|
*/
|
||||||
public class ReadPreparationExchange implements MessageExchange<ReadPreparationExchange.Request, ReadPreparationExchange.Response> {
|
public class ReadPreparationExchange implements MessageExchange<ReadPreparationExchange.Request, ReadPreparationExchange.Response> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,6 +6,9 @@ import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the daemon to stop.
|
||||||
|
*/
|
||||||
public class StopExchange implements MessageExchange<StopExchange.Request, StopExchange.Response> {
|
public class StopExchange implements MessageExchange<StopExchange.Request, StopExchange.Response> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
package io.xpipe.beacon.exchange;
|
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
|
||||||
import io.xpipe.core.source.DataSourceConfigOptions;
|
|
||||||
import io.xpipe.core.source.DataSourceId;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Value;
|
|
||||||
import lombok.extern.jackson.Jacksonized;
|
|
||||||
|
|
||||||
public class StoreEditExchange implements MessageExchange<StoreEditExchange.Request, StoreEditExchange.Response> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return "storeEdit";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<StoreEditExchange.Request> getRequestClass() {
|
|
||||||
return StoreEditExchange.Request.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<StoreEditExchange.Response> getResponseClass() {
|
|
||||||
return StoreEditExchange.Response.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
|
||||||
@Builder
|
|
||||||
@Value
|
|
||||||
public static class Request implements RequestMessage {
|
|
||||||
DataSourceId sourceId;
|
|
||||||
DataSourceConfigOptions config;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
|
||||||
@Builder
|
|
||||||
@Value
|
|
||||||
public static class Response implements ResponseMessage {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,13 +2,14 @@ package io.xpipe.beacon.exchange;
|
||||||
|
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.store.StreamDataStore;
|
||||||
import io.xpipe.core.source.DataSourceType;
|
|
||||||
import io.xpipe.core.source.DataSourceConfigOptions;
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a stream of data in a storage.
|
||||||
|
*/
|
||||||
public class StoreStreamExchange implements MessageExchange<StoreStreamExchange.Request, StoreStreamExchange.Response> {
|
public class StoreStreamExchange implements MessageExchange<StoreStreamExchange.Request, StoreStreamExchange.Response> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -30,16 +31,12 @@ public class StoreStreamExchange implements MessageExchange<StoreStreamExchange.
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {
|
||||||
String type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {
|
||||||
DataSourceId sourceId;
|
StreamDataStore store;
|
||||||
DataSourceType sourceType;
|
|
||||||
DataSourceConfigOptions config;
|
|
||||||
Object data;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@ import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries data of a table data source in the xpbt format.
|
||||||
|
*/
|
||||||
public class QueryTableDataExchange implements MessageExchange<QueryTableDataExchange.Request, QueryTableDataExchange.Response> {
|
public class QueryTableDataExchange implements MessageExchange<QueryTableDataExchange.Request, QueryTableDataExchange.Response> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
import io.xpipe.core.source.DataSourceConfigInstance;
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
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.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
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.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
import io.xpipe.core.source.DataSourceConfigInstance;
|
||||||
|
@ -10,6 +11,9 @@ import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output the data source contents.
|
||||||
|
*/
|
||||||
public class WriteExecuteExchange implements MessageExchange<WriteExecuteExchange.Request, WriteExecuteExchange.Response> {
|
public class WriteExecuteExchange implements MessageExchange<WriteExecuteExchange.Request, WriteExecuteExchange.Response> {
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.beacon.exchange;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
import io.xpipe.core.source.DataSourceConfigInstance;
|
||||||
|
@ -10,6 +11,9 @@ import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares a client to output the data source contents.
|
||||||
|
*/
|
||||||
public class WritePreparationExchange implements MessageExchange<WritePreparationExchange.Request, WritePreparationExchange.Response> {
|
public class WritePreparationExchange implements MessageExchange<WritePreparationExchange.Request, WritePreparationExchange.Response> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,7 +35,7 @@ public class WritePreparationExchange implements MessageExchange<WritePreparatio
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {
|
||||||
String providerType;
|
String type;
|
||||||
String output;
|
String output;
|
||||||
@NonNull
|
@NonNull
|
||||||
DataSourceReference ref;
|
DataSourceReference ref;
|
||||||
|
@ -41,7 +45,7 @@ public class WritePreparationExchange implements MessageExchange<WritePreparatio
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {
|
||||||
DataStore dataStore;
|
DataStore store;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
DataSourceConfigInstance config;
|
DataSourceConfigInstance config;
|
|
@ -1,5 +1,6 @@
|
||||||
import io.xpipe.beacon.exchange.*;
|
import io.xpipe.beacon.exchange.*;
|
||||||
import io.xpipe.beacon.exchange.api.QueryTableDataExchange;
|
import io.xpipe.beacon.exchange.api.*;
|
||||||
|
import io.xpipe.beacon.exchange.cli.*;
|
||||||
|
|
||||||
module io.xpipe.beacon {
|
module io.xpipe.beacon {
|
||||||
exports io.xpipe.beacon;
|
exports io.xpipe.beacon;
|
||||||
|
@ -7,12 +8,14 @@ module io.xpipe.beacon {
|
||||||
exports io.xpipe.beacon.message;
|
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;
|
||||||
|
|
||||||
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.message;
|
||||||
opens io.xpipe.beacon.exchange.data;
|
opens io.xpipe.beacon.exchange.data;
|
||||||
|
opens io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
requires com.fasterxml.jackson.core;
|
requires com.fasterxml.jackson.core;
|
||||||
requires com.fasterxml.jackson.databind;
|
requires com.fasterxml.jackson.databind;
|
||||||
|
@ -33,7 +36,7 @@ module io.xpipe.beacon {
|
||||||
ReadExecuteExchange,
|
ReadExecuteExchange,
|
||||||
DialogExchange,
|
DialogExchange,
|
||||||
QueryDataSourceExchange,
|
QueryDataSourceExchange,
|
||||||
PreStoreExchange,
|
StoreStreamExchange,
|
||||||
EditPreparationExchange,
|
EditPreparationExchange,
|
||||||
EditExecuteExchange,
|
EditExecuteExchange,
|
||||||
QueryTableDataExchange,
|
QueryTableDataExchange,
|
||||||
|
|
|
@ -4,8 +4,8 @@ publishing {
|
||||||
from components.java
|
from components.java
|
||||||
|
|
||||||
pom {
|
pom {
|
||||||
name = 'X-Pipe core'
|
name = 'X-Pipe Core'
|
||||||
description = 'Core classes ued by all X-Pipe components.'
|
description = 'Core classes used by all X-Pipe components.'
|
||||||
url = 'https://github.com/xpipe-io/xpipe_java/core'
|
url = 'https://github.com/xpipe-io/xpipe_java/core'
|
||||||
licenses {
|
licenses {
|
||||||
license {
|
license {
|
||||||
|
|
|
@ -11,12 +11,12 @@ public abstract class TupleNode extends DataStructureNode {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TupleNode of(List<? extends DataStructureNode> nodes) {
|
public static TupleNode of(List<DataStructureNode> nodes) {
|
||||||
if (nodes == null) {
|
if (nodes == null) {
|
||||||
throw new IllegalArgumentException("Nodes must be not null");
|
throw new IllegalArgumentException("Nodes must be not null");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NoKeyTupleNode(true, (List<DataStructureNode>) nodes);
|
return new NoKeyTupleNode(true, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TupleNode of(List<String> names, List<DataStructureNode> nodes) {
|
public static TupleNode of(List<String> names, List<DataStructureNode> nodes) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package io.xpipe.core.store;
|
package io.xpipe.core.store;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
@ -19,27 +18,7 @@ public class OutputStreamStore implements StreamDataStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OutputStream openOutput() throws Exception {
|
public OutputStream openOutput() throws Exception {
|
||||||
return new OutputStream() {
|
return out;
|
||||||
@Override
|
|
||||||
public void write(int b) throws IOException {
|
|
||||||
out.write(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(byte[] b, int off, int len) throws IOException {
|
|
||||||
out.write(b, off, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(byte[] b) throws IOException {
|
|
||||||
out.write(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush() throws IOException {
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package io.xpipe.core.util;
|
package io.xpipe.core.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||||
|
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
@ -103,6 +105,9 @@ public class CoreJacksonModule extends SimpleModule {
|
||||||
|
|
||||||
@JsonSerialize(as = Throwable.class)
|
@JsonSerialize(as = Throwable.class)
|
||||||
public abstract static class ThrowableTypeMixIn {
|
public abstract static class ThrowableTypeMixIn {
|
||||||
|
|
||||||
|
@JsonIdentityInfo(generator= ObjectIdGenerators.StringIdGenerator.class, property="$id")
|
||||||
|
private Throwable cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonSerialize(as = DataSourceReference.class)
|
@JsonSerialize(as = DataSourceReference.class)
|
||||||
|
|
|
@ -1,27 +1,26 @@
|
||||||
import io.xpipe.core.util.CoreJacksonModule;
|
import io.xpipe.core.util.CoreJacksonModule;
|
||||||
|
|
||||||
module io.xpipe.core {
|
module io.xpipe.core {
|
||||||
requires com.fasterxml.jackson.core;
|
|
||||||
requires com.fasterxml.jackson.databind;
|
|
||||||
|
|
||||||
requires static lombok;
|
|
||||||
|
|
||||||
exports io.xpipe.core.store;
|
exports io.xpipe.core.store;
|
||||||
exports io.xpipe.core.source;
|
exports io.xpipe.core.source;
|
||||||
exports io.xpipe.core.data.generic;
|
exports io.xpipe.core.data.generic;
|
||||||
exports io.xpipe.core.data.type;
|
exports io.xpipe.core.data.type;
|
||||||
|
exports io.xpipe.core.util;
|
||||||
|
exports io.xpipe.core.data.node;
|
||||||
|
exports io.xpipe.core.data.typed;
|
||||||
|
|
||||||
opens io.xpipe.core.store;
|
opens io.xpipe.core.store;
|
||||||
opens io.xpipe.core.source;
|
opens io.xpipe.core.source;
|
||||||
opens io.xpipe.core.data.type;
|
opens io.xpipe.core.data.type;
|
||||||
opens io.xpipe.core.data.generic;
|
opens io.xpipe.core.data.generic;
|
||||||
exports io.xpipe.core.util;
|
|
||||||
opens io.xpipe.core.util;
|
opens io.xpipe.core.util;
|
||||||
exports io.xpipe.core.data.node;
|
|
||||||
opens io.xpipe.core.data.node;
|
opens io.xpipe.core.data.node;
|
||||||
exports io.xpipe.core.data.typed;
|
|
||||||
opens io.xpipe.core.data.typed;
|
opens io.xpipe.core.data.typed;
|
||||||
|
|
||||||
|
requires com.fasterxml.jackson.core;
|
||||||
|
requires com.fasterxml.jackson.databind;
|
||||||
|
requires static lombok;
|
||||||
|
|
||||||
uses com.fasterxml.jackson.databind.Module;
|
uses com.fasterxml.jackson.databind.Module;
|
||||||
provides com.fasterxml.jackson.databind.Module with CoreJacksonModule;
|
provides com.fasterxml.jackson.databind.Module with CoreJacksonModule;
|
||||||
}
|
}
|
|
@ -27,5 +27,4 @@ repositories {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':core')
|
implementation project(':core')
|
||||||
implementation project(':fxcomps')
|
implementation project(':fxcomps')
|
||||||
implementation group: 'com.dlsc.preferencesfx', name: 'preferencesfx-core', version: '11.8.0'
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ publishing {
|
||||||
from components.java
|
from components.java
|
||||||
|
|
||||||
pom {
|
pom {
|
||||||
name = 'X-Pipe extension base'
|
name = 'X-Pipe Extension Base'
|
||||||
description = 'Classes required to create X-Pipe extensions.'
|
description = 'Classes required to create X-Pipe extensions.'
|
||||||
url = 'https://github.com/xpipe-io/xpipe_java/extension'
|
url = 'https://github.com/xpipe-io/xpipe_java/extension'
|
||||||
licenses {
|
licenses {
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
package io.xpipe.extension.prefs;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
|
||||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
|
||||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
|
||||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PrefsChoiceValueModule extends SimpleModule {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setupModule(SetupContext context) {
|
|
||||||
addSerializer(PrefsChoiceValue.class, new PrefsChoiceValueSerializer());
|
|
||||||
addDeserializer(PrefsChoiceValue.class, new PrefsChoiceValueDeserializer());
|
|
||||||
|
|
||||||
context.addSerializers(_serializers);
|
|
||||||
context.addDeserializers(_deserializers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PrefsChoiceValueSerializer extends JsonSerializer<PrefsChoiceValue> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void serialize(PrefsChoiceValue value, JsonGenerator jgen, SerializerProvider provider)
|
|
||||||
throws IOException {
|
|
||||||
jgen.writeString(value.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PrefsChoiceValueDeserializer extends JsonDeserializer<PrefsChoiceValue> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PrefsChoiceValue deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
|
||||||
var id = p.getValueAsString();
|
|
||||||
Class<? extends PrefsChoiceValue> clazz = (Class<? extends PrefsChoiceValue>) ctxt.getContextualType().getRawClass();
|
|
||||||
try {
|
|
||||||
var list = (List<? extends PrefsChoiceValue>) clazz.getDeclaredField("SUPPORTED").get(null);
|
|
||||||
return list.stream().filter(v -> v.getId().equals(id)).findAny().orElse(null);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,12 @@
|
||||||
import com.fasterxml.jackson.databind.Module;
|
|
||||||
import io.xpipe.extension.DataSourceProvider;
|
import io.xpipe.extension.DataSourceProvider;
|
||||||
import io.xpipe.extension.SupportedApplicationProvider;
|
import io.xpipe.extension.SupportedApplicationProvider;
|
||||||
import io.xpipe.extension.prefs.PrefsChoiceValueModule;
|
|
||||||
|
|
||||||
module io.xpipe.extension {
|
module io.xpipe.extension {
|
||||||
|
exports io.xpipe.extension;
|
||||||
|
exports io.xpipe.extension.comp;
|
||||||
|
exports io.xpipe.extension.event;
|
||||||
|
exports io.xpipe.extension.prefs;
|
||||||
|
|
||||||
requires io.xpipe.core;
|
requires io.xpipe.core;
|
||||||
requires javafx.base;
|
requires javafx.base;
|
||||||
requires javafx.graphics;
|
requires javafx.graphics;
|
||||||
|
@ -11,20 +14,6 @@ module io.xpipe.extension {
|
||||||
requires io.xpipe.fxcomps;
|
requires io.xpipe.fxcomps;
|
||||||
requires org.apache.commons.collections4;
|
requires org.apache.commons.collections4;
|
||||||
requires static lombok;
|
requires static lombok;
|
||||||
|
|
||||||
exports io.xpipe.extension;
|
|
||||||
exports io.xpipe.extension.comp;
|
|
||||||
exports io.xpipe.extension.event;
|
|
||||||
exports io.xpipe.extension.prefs;
|
|
||||||
|
|
||||||
uses DataSourceProvider;
|
|
||||||
uses SupportedApplicationProvider;
|
|
||||||
uses io.xpipe.extension.I18n;
|
|
||||||
uses io.xpipe.extension.event.EventHandler;
|
|
||||||
uses io.xpipe.extension.prefs.PrefsProvider;
|
|
||||||
|
|
||||||
provides Module with PrefsChoiceValueModule;
|
|
||||||
|
|
||||||
requires com.dlsc.preferencesfx;
|
requires com.dlsc.preferencesfx;
|
||||||
requires com.dlsc.formsfx;
|
requires com.dlsc.formsfx;
|
||||||
requires java.desktop;
|
requires java.desktop;
|
||||||
|
@ -35,4 +24,10 @@ module io.xpipe.extension {
|
||||||
requires org.reactfx;
|
requires org.reactfx;
|
||||||
requires org.kordamp.ikonli.javafx;
|
requires org.kordamp.ikonli.javafx;
|
||||||
requires com.fasterxml.jackson.databind;
|
requires com.fasterxml.jackson.databind;
|
||||||
|
|
||||||
|
uses DataSourceProvider;
|
||||||
|
uses SupportedApplicationProvider;
|
||||||
|
uses io.xpipe.extension.I18n;
|
||||||
|
uses io.xpipe.extension.event.EventHandler;
|
||||||
|
uses io.xpipe.extension.prefs.PrefsProvider;
|
||||||
}
|
}
|
2
version
2
version
|
@ -1 +1 @@
|
||||||
0.1
|
0.1-SNAPSHOT
|
Loading…
Reference in a new issue