mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-23 08:00:23 +00:00
Refactor
This commit is contained in:
parent
a351b92ac7
commit
55e254a54c
27 changed files with 350 additions and 333 deletions
|
@ -1,6 +1,6 @@
|
|||
package io.xpipe.api;
|
||||
|
||||
import io.xpipe.api.connector.XPipeConnection;
|
||||
import io.xpipe.api.connector.XPipeApiConnection;
|
||||
import io.xpipe.api.util.QuietDialogHandler;
|
||||
import io.xpipe.beacon.exchange.cli.StoreAddExchange;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
|
@ -10,7 +10,7 @@ import java.util.Map;
|
|||
public class DataStores {
|
||||
|
||||
public static void addNamedStore(DataStore store, String name) {
|
||||
XPipeConnection.execute(con -> {
|
||||
XPipeApiConnection.execute(con -> {
|
||||
var req = StoreAddExchange.Request.builder()
|
||||
.storeInput(store)
|
||||
.name(name)
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
package io.xpipe.api.connector;
|
||||
|
||||
import io.xpipe.beacon.*;
|
||||
import io.xpipe.beacon.BeaconClient;
|
||||
import io.xpipe.beacon.BeaconConnection;
|
||||
import io.xpipe.beacon.BeaconException;
|
||||
import io.xpipe.beacon.BeaconServer;
|
||||
import io.xpipe.beacon.exchange.cli.DialogExchange;
|
||||
import io.xpipe.core.dialog.DialogReference;
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class XPipeConnection extends BeaconConnection {
|
||||
public final class XPipeApiConnection extends BeaconConnection {
|
||||
|
||||
private XPipeConnection() {}
|
||||
private XPipeApiConnection() {}
|
||||
|
||||
public static XPipeConnection open() {
|
||||
var con = new XPipeConnection();
|
||||
public static XPipeApiConnection open() {
|
||||
var con = new XPipeApiConnection();
|
||||
con.constructSocket();
|
||||
return con;
|
||||
}
|
||||
|
||||
public static void finishDialog(DialogReference reference) {
|
||||
try (var con = new XPipeConnection()) {
|
||||
try (var con = new XPipeApiConnection()) {
|
||||
con.constructSocket();
|
||||
var element = reference.getStart();
|
||||
while (true) {
|
||||
|
@ -41,7 +45,7 @@ public final class XPipeConnection extends BeaconConnection {
|
|||
}
|
||||
|
||||
public static void execute(Handler handler) {
|
||||
try (var con = new XPipeConnection()) {
|
||||
try (var con = new XPipeApiConnection()) {
|
||||
con.constructSocket();
|
||||
handler.handle(con);
|
||||
} catch (BeaconException e) {
|
||||
|
@ -52,7 +56,7 @@ public final class XPipeConnection extends BeaconConnection {
|
|||
}
|
||||
|
||||
public static <T> T execute(Mapper<T> mapper) {
|
||||
try (var con = new XPipeConnection()) {
|
||||
try (var con = new XPipeApiConnection()) {
|
||||
con.constructSocket();
|
||||
return mapper.handle(con);
|
||||
} catch (BeaconException e) {
|
||||
|
@ -73,7 +77,10 @@ public final class XPipeConnection extends BeaconConnection {
|
|||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
|
||||
var s = BeaconClient.tryConnect(BeaconClient.ApiClientInformation.builder().version("?").language("Java").build());
|
||||
var s = BeaconClient.tryConnect(BeaconClient.ApiClientInformation.builder()
|
||||
.version("?")
|
||||
.language("Java")
|
||||
.build());
|
||||
if (s.isPresent()) {
|
||||
return s;
|
||||
}
|
||||
|
@ -114,17 +121,18 @@ public final class XPipeConnection extends BeaconConnection {
|
|||
}
|
||||
|
||||
try {
|
||||
beaconClient = BeaconClient.connect(BeaconClient.ApiClientInformation.builder().version("?").language("Java").build());
|
||||
beaconClient = BeaconClient.connect(BeaconClient.ApiClientInformation.builder()
|
||||
.version("?")
|
||||
.language("Java")
|
||||
.build());
|
||||
} catch (Exception ex) {
|
||||
throw new BeaconException("Unable to connect to running xpipe daemon", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void start() throws Exception {
|
||||
if (BeaconServer.tryStart() == null) {
|
||||
throw new UnsupportedOperationException("Unable to determine xpipe daemon launch command");
|
||||
}
|
||||
;
|
||||
var installation = XPipeInstallation.getDefaultInstallationBasePath();
|
||||
BeaconServer.start(installation);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
|
@ -2,7 +2,7 @@ package io.xpipe.api.impl;
|
|||
|
||||
import io.xpipe.api.DataSource;
|
||||
import io.xpipe.api.DataSourceConfig;
|
||||
import io.xpipe.api.connector.XPipeConnection;
|
||||
import io.xpipe.api.connector.XPipeApiConnection;
|
||||
import io.xpipe.beacon.exchange.*;
|
||||
import io.xpipe.core.source.DataSourceId;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
|
@ -25,7 +25,7 @@ public abstract class DataSourceImpl implements DataSource {
|
|||
}
|
||||
|
||||
public static DataSource get(DataSourceReference ds) {
|
||||
return XPipeConnection.execute(con -> {
|
||||
return XPipeApiConnection.execute(con -> {
|
||||
var req = QueryDataSourceExchange.Request.builder().ref(ds).build();
|
||||
QueryDataSourceExchange.Response res = con.performSimpleExchange(req);
|
||||
var config = new DataSourceConfig(res.getProvider(), res.getConfig());
|
||||
|
@ -53,7 +53,7 @@ public abstract class DataSourceImpl implements DataSource {
|
|||
public static DataSource create(DataSourceId id, io.xpipe.core.source.DataSource<?> source) {
|
||||
var startReq =
|
||||
AddSourceExchange.Request.builder().source(source).target(id).build();
|
||||
var returnedId = XPipeConnection.execute(con -> {
|
||||
var returnedId = XPipeApiConnection.execute(con -> {
|
||||
AddSourceExchange.Response r = con.performSimpleExchange(startReq);
|
||||
return r.getId();
|
||||
});
|
||||
|
@ -64,7 +64,7 @@ public abstract class DataSourceImpl implements DataSource {
|
|||
|
||||
public static DataSource create(DataSourceId id, String type, DataStore store) {
|
||||
if (store instanceof StreamDataStore s && s.isContentExclusivelyAccessible()) {
|
||||
var res = XPipeConnection.execute(con -> {
|
||||
var res = XPipeApiConnection.execute(con -> {
|
||||
var req = StoreStreamExchange.Request.builder().build();
|
||||
StoreStreamExchange.Response r = con.performOutputExchange(req, out -> {
|
||||
try (InputStream inputStream = s.openInput()) {
|
||||
|
@ -83,20 +83,20 @@ public abstract class DataSourceImpl implements DataSource {
|
|||
.target(id)
|
||||
.configureAll(false)
|
||||
.build();
|
||||
var startRes = XPipeConnection.execute(con -> {
|
||||
var startRes = XPipeApiConnection.execute(con -> {
|
||||
ReadExchange.Response r = con.performSimpleExchange(startReq);
|
||||
return r;
|
||||
});
|
||||
|
||||
var configInstance = startRes.getConfig();
|
||||
XPipeConnection.finishDialog(configInstance);
|
||||
XPipeApiConnection.finishDialog(configInstance);
|
||||
|
||||
var ref = id != null ? DataSourceReference.id(id) : DataSourceReference.latest();
|
||||
return get(ref);
|
||||
}
|
||||
|
||||
public static DataSource create(DataSourceId id, String type, InputStream in) {
|
||||
var res = XPipeConnection.execute(con -> {
|
||||
var res = XPipeApiConnection.execute(con -> {
|
||||
var req = StoreStreamExchange.Request.builder().build();
|
||||
StoreStreamExchange.Response r = con.performOutputExchange(req, out -> in.transferTo(out));
|
||||
return r;
|
||||
|
@ -110,13 +110,13 @@ public abstract class DataSourceImpl implements DataSource {
|
|||
.target(id)
|
||||
.configureAll(false)
|
||||
.build();
|
||||
var startRes = XPipeConnection.execute(con -> {
|
||||
var startRes = XPipeApiConnection.execute(con -> {
|
||||
ReadExchange.Response r = con.performSimpleExchange(startReq);
|
||||
return r;
|
||||
});
|
||||
|
||||
var configInstance = startRes.getConfig();
|
||||
XPipeConnection.finishDialog(configInstance);
|
||||
XPipeApiConnection.finishDialog(configInstance);
|
||||
|
||||
var ref = id != null ? DataSourceReference.id(id) : DataSourceReference.latest();
|
||||
return get(ref);
|
||||
|
@ -124,7 +124,7 @@ public abstract class DataSourceImpl implements DataSource {
|
|||
|
||||
@Override
|
||||
public void forwardTo(DataSource target) {
|
||||
XPipeConnection.execute(con -> {
|
||||
XPipeApiConnection.execute(con -> {
|
||||
var req = ForwardExchange.Request.builder()
|
||||
.source(DataSourceReference.id(sourceId))
|
||||
.target(DataSourceReference.id(target.getId()))
|
||||
|
@ -135,7 +135,7 @@ public abstract class DataSourceImpl implements DataSource {
|
|||
|
||||
@Override
|
||||
public void appendTo(DataSource target) {
|
||||
XPipeConnection.execute(con -> {
|
||||
XPipeApiConnection.execute(con -> {
|
||||
var req = ForwardExchange.Request.builder()
|
||||
.source(DataSourceReference.id(sourceId))
|
||||
.target(DataSourceReference.id(target.getId()))
|
||||
|
|
|
@ -3,7 +3,7 @@ package io.xpipe.api.impl;
|
|||
import io.xpipe.api.DataSource;
|
||||
import io.xpipe.api.DataTable;
|
||||
import io.xpipe.api.DataTableAccumulator;
|
||||
import io.xpipe.api.connector.XPipeConnection;
|
||||
import io.xpipe.api.connector.XPipeApiConnection;
|
||||
import io.xpipe.api.util.TypeDescriptor;
|
||||
import io.xpipe.beacon.BeaconException;
|
||||
import io.xpipe.beacon.exchange.ReadExchange;
|
||||
|
@ -22,7 +22,7 @@ import java.nio.charset.StandardCharsets;
|
|||
|
||||
public class DataTableAccumulatorImpl implements DataTableAccumulator {
|
||||
|
||||
private final XPipeConnection connection;
|
||||
private final XPipeApiConnection connection;
|
||||
private final TupleType type;
|
||||
private int rows;
|
||||
private TupleType writtenDescriptor;
|
||||
|
@ -30,7 +30,7 @@ public class DataTableAccumulatorImpl implements DataTableAccumulator {
|
|||
|
||||
public DataTableAccumulatorImpl(TupleType type) {
|
||||
this.type = type;
|
||||
connection = XPipeConnection.open();
|
||||
connection = XPipeApiConnection.open();
|
||||
connection.sendRequest(StoreStreamExchange.Request.builder().build());
|
||||
bodyOutput = connection.sendBody();
|
||||
}
|
||||
|
@ -52,12 +52,12 @@ public class DataTableAccumulatorImpl implements DataTableAccumulator {
|
|||
.provider("xpbt")
|
||||
.configureAll(false)
|
||||
.build();
|
||||
ReadExchange.Response response = XPipeConnection.execute(con -> {
|
||||
ReadExchange.Response response = XPipeApiConnection.execute(con -> {
|
||||
return con.performSimpleExchange(req);
|
||||
});
|
||||
|
||||
var configInstance = response.getConfig();
|
||||
XPipeConnection.finishDialog(configInstance);
|
||||
XPipeApiConnection.finishDialog(configInstance);
|
||||
|
||||
return DataSource.get(DataSourceReference.id(id)).asTable();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package io.xpipe.api.impl;
|
|||
|
||||
import io.xpipe.api.DataSourceConfig;
|
||||
import io.xpipe.api.DataTable;
|
||||
import io.xpipe.api.connector.XPipeConnection;
|
||||
import io.xpipe.api.connector.XPipeApiConnection;
|
||||
import io.xpipe.beacon.BeaconConnection;
|
||||
import io.xpipe.beacon.BeaconException;
|
||||
import io.xpipe.beacon.exchange.api.QueryTableDataExchange;
|
||||
|
@ -55,7 +55,7 @@ public class DataTableImpl extends DataSourceImpl implements DataTable {
|
|||
@Override
|
||||
public ArrayNode read(int maxRows) {
|
||||
List<DataStructureNode> nodes = new ArrayList<>();
|
||||
XPipeConnection.execute(con -> {
|
||||
XPipeApiConnection.execute(con -> {
|
||||
var req = QueryTableDataExchange.Request.builder()
|
||||
.ref(DataSourceReference.id(getId()))
|
||||
.maxRows(maxRows)
|
||||
|
@ -83,7 +83,7 @@ public class DataTableImpl extends DataSourceImpl implements DataTable {
|
|||
private TupleNode node;
|
||||
|
||||
{
|
||||
connection = XPipeConnection.open();
|
||||
connection = XPipeApiConnection.open();
|
||||
var req = QueryTableDataExchange.Request.builder()
|
||||
.ref(DataSourceReference.id(getId()))
|
||||
.maxRows(Integer.MAX_VALUE)
|
||||
|
|
|
@ -2,7 +2,7 @@ package io.xpipe.api.impl;
|
|||
|
||||
import io.xpipe.api.DataSourceConfig;
|
||||
import io.xpipe.api.DataText;
|
||||
import io.xpipe.api.connector.XPipeConnection;
|
||||
import io.xpipe.api.connector.XPipeApiConnection;
|
||||
import io.xpipe.beacon.BeaconConnection;
|
||||
import io.xpipe.beacon.BeaconException;
|
||||
import io.xpipe.beacon.exchange.api.QueryTextDataExchange;
|
||||
|
@ -62,7 +62,7 @@ public class DataTextImpl extends DataSourceImpl implements DataText {
|
|||
private String nextValue;
|
||||
|
||||
{
|
||||
connection = XPipeConnection.open();
|
||||
connection = XPipeApiConnection.open();
|
||||
var req = QueryTextDataExchange.Request.builder()
|
||||
.ref(DataSourceReference.id(getId()))
|
||||
.maxLines(-1)
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package io.xpipe.api.util;
|
||||
|
||||
import io.xpipe.api.connector.XPipeConnection;
|
||||
import io.xpipe.beacon.BeaconClient;
|
||||
import io.xpipe.beacon.BeaconServer;
|
||||
|
||||
public class XPipeDaemonController {
|
||||
|
||||
private static boolean alreadyStarted;
|
||||
|
||||
public static void start() throws Exception {
|
||||
if (BeaconServer.isRunning()) {
|
||||
alreadyStarted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Process process = null;
|
||||
if ((process = BeaconServer.tryStartCustom()) != null) {
|
||||
} else {
|
||||
if ((process = BeaconServer.tryStart()) == null) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
XPipeConnection.waitForStartup(process).orElseThrow();
|
||||
if (!BeaconServer.isRunning()) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stop() throws Exception {
|
||||
if (alreadyStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!BeaconServer.isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var client = BeaconClient.connect(BeaconClient.ApiClientInformation.builder().version("?").language("Java API Test").build());
|
||||
if (!BeaconServer.tryStop(client)) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
XPipeConnection.waitForShutdown();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package io.xpipe.api.test;
|
||||
|
||||
import io.xpipe.api.util.XPipeDaemonController;
|
||||
import io.xpipe.beacon.BeaconDaemonController;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
|
@ -8,11 +8,11 @@ public class ApiTest {
|
|||
|
||||
@BeforeAll
|
||||
public static void setup() throws Exception {
|
||||
XPipeDaemonController.start();
|
||||
BeaconDaemonController.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void teardown() throws Exception {
|
||||
XPipeDaemonController.stop();
|
||||
BeaconDaemonController.stop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import io.xpipe.beacon.exchange.MessageExchanges;
|
|||
import io.xpipe.beacon.exchange.data.ClientErrorMessage;
|
||||
import io.xpipe.beacon.exchange.data.ServerErrorMessage;
|
||||
import io.xpipe.core.process.CommandProcessControl;
|
||||
import io.xpipe.core.store.ShellStore;
|
||||
import io.xpipe.core.util.JacksonMapper;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
@ -47,12 +48,11 @@ public class BeaconClient implements AutoCloseable {
|
|||
@EqualsAndHashCode(callSuper = false)
|
||||
public static class CliClientInformation extends ClientInformation {
|
||||
|
||||
String version;
|
||||
int consoleWidth;
|
||||
|
||||
@Override
|
||||
public String toDisplayString() {
|
||||
return "X-Pipe CLI " + version;
|
||||
return "X-Pipe CLI";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,16 @@ public class BeaconClient implements AutoCloseable {
|
|||
return client;
|
||||
}
|
||||
|
||||
public static BeaconClient connectGateway(CommandProcessControl control, GatewayClientInformation information) throws Exception {
|
||||
public static BeaconClient connectProxy(ShellStore proxy) throws Exception {
|
||||
var control = proxy.create().start();
|
||||
var command = control.command("xpipe beacon").start();
|
||||
return BeaconClient.connectGateway(
|
||||
command,
|
||||
BeaconClient.GatewayClientInformation.builder()
|
||||
.build());
|
||||
}
|
||||
|
||||
private static BeaconClient connectGateway(CommandProcessControl control, GatewayClientInformation information) throws Exception {
|
||||
var client = new BeaconClient(() -> {}, control.getStdout(), control.getStdin());
|
||||
client.sendObject(JacksonMapper.newMapper().valueToTree(information));
|
||||
return client;
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package io.xpipe.beacon;
|
||||
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BeaconDaemonController {
|
||||
|
||||
private static boolean alreadyStarted;
|
||||
|
||||
public static void start() throws Exception {
|
||||
if (BeaconServer.isRunning()) {
|
||||
alreadyStarted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var custom = false;
|
||||
Process process;
|
||||
if ((process = BeaconServer.tryStartCustom()) != null) {
|
||||
custom = true;
|
||||
} else {
|
||||
var defaultBase = XPipeInstallation.getDefaultInstallationBasePath();
|
||||
process = BeaconServer.start(defaultBase);
|
||||
}
|
||||
|
||||
waitForStartup(process, custom);
|
||||
if (!BeaconServer.isRunning()) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stop() throws Exception {
|
||||
if (alreadyStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!BeaconServer.isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var client = BeaconClient.connect(BeaconClient.ApiClientInformation.builder().version("?").language("Java API Test").build());
|
||||
if (!BeaconServer.tryStop(client)) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
waitForShutdown();
|
||||
}
|
||||
|
||||
private static void waitForStartup(Process process, boolean custom) throws IOException {
|
||||
for (int i = 0; i < 160; i++) {
|
||||
if (process != null && !custom && !process.isAlive()) {
|
||||
throw new IOException("Daemon start failed");
|
||||
}
|
||||
|
||||
if (process != null && custom && !process.isAlive() && process.exitValue() != 0) {
|
||||
throw new IOException("Custom launch command failed");
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
|
||||
var s = BeaconClient.tryConnect(BeaconClient.ApiClientInformation.builder()
|
||||
.version("?")
|
||||
.language("Java")
|
||||
.build());
|
||||
if (s.isPresent()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IOException("Wait for daemon start up timed out");
|
||||
}
|
||||
|
||||
private static void waitForShutdown() {
|
||||
for (int i = 0; i < 40; i++) {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
|
||||
var r = BeaconServer.isRunning();
|
||||
if (!r) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,15 @@
|
|||
package io.xpipe.beacon;
|
||||
|
||||
import io.xpipe.beacon.exchange.StopExchange;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.impl.FileNames;
|
||||
import io.xpipe.core.impl.LocalStore;
|
||||
import io.xpipe.core.process.ShellProcessControl;
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Contains basic functionality to start, communicate, and stop a remote beacon server.
|
||||
|
@ -16,16 +17,8 @@ import java.util.Optional;
|
|||
@UtilityClass
|
||||
public class BeaconServer {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (tryStartCustom() == null) {
|
||||
if (tryStart() == null) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isRunning() {
|
||||
try (var socket = BeaconClient.connect(null)) {
|
||||
try (var ignored = BeaconClient.connect(null)) {
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
|
@ -44,18 +37,14 @@ public class BeaconServer {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static Process tryStart() throws Exception {
|
||||
var daemonExecutable = getDaemonExecutable();
|
||||
if (daemonExecutable.isPresent()) {
|
||||
var command = "\"" + daemonExecutable.get() + "\" --external "
|
||||
+ (BeaconConfig.getDaemonArguments() != null ? BeaconConfig.getDaemonArguments() : "");
|
||||
// Tell daemon that we launched from an external tool
|
||||
Process process = Runtime.getRuntime().exec(command);
|
||||
printDaemonOutput(process, command);
|
||||
return process;
|
||||
}
|
||||
|
||||
return null;
|
||||
public static Process start(String installationBase) throws Exception {
|
||||
var daemonExecutable = getDaemonExecutable(installationBase);
|
||||
// Tell daemon that we launched from an external tool
|
||||
var command = "\"" + daemonExecutable + "\" --external "
|
||||
+ (BeaconConfig.getDaemonArguments() != null ? BeaconConfig.getDaemonArguments() : "");
|
||||
Process process = Runtime.getRuntime().exec(command);
|
||||
printDaemonOutput(process, command);
|
||||
return process;
|
||||
}
|
||||
|
||||
private static void printDaemonOutput(Process proc, String command) {
|
||||
|
@ -111,65 +100,21 @@ public class BeaconServer {
|
|||
return res.isSuccess();
|
||||
}
|
||||
|
||||
private static Optional<Path> getDaemonBasePath(OsType type) {
|
||||
Path base = null;
|
||||
// Prepare for invalid XPIPE_HOME path value
|
||||
try {
|
||||
var environmentVariable = System.getenv("XPIPE_HOME");
|
||||
base = environmentVariable != null ? Path.of(environmentVariable) : null;
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
|
||||
if (base == null) {
|
||||
if (type.equals(OsType.WINDOWS)) {
|
||||
base = Path.of(System.getenv("LOCALAPPDATA"), "X-Pipe");
|
||||
public static Path getDaemonExecutable(String installationBase) throws Exception {
|
||||
try (ShellProcessControl pc = new LocalStore().create().start()) {
|
||||
var debug = BeaconConfig.launchDaemonInDebugMode();
|
||||
if (!debug) {
|
||||
return Path.of(
|
||||
FileNames.join(installationBase, XPipeInstallation.getDaemonExecutablePath(pc.getOsType())));
|
||||
} else {
|
||||
base = Path.of("/opt/xpipe/");
|
||||
if (BeaconConfig.attachDebuggerToDaemon()) {
|
||||
return Path.of(FileNames.join(
|
||||
installationBase, XPipeInstallation.getDaemonDebugAttachScriptPath(pc.getOsType())));
|
||||
} else {
|
||||
return Path.of(FileNames.join(
|
||||
installationBase, XPipeInstallation.getDaemonDebugScriptPath(pc.getOsType())));
|
||||
}
|
||||
}
|
||||
if (!Files.exists(base)) {
|
||||
base = null;
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.ofNullable(base);
|
||||
}
|
||||
|
||||
public static Path getDaemonExecutableInBaseDirectory(OsType type) {
|
||||
if (type.equals(OsType.WINDOWS)) {
|
||||
return Path.of("app", "runtime", "bin", "xpiped.bat");
|
||||
} else {
|
||||
return Path.of("app/bin/xpiped");
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<Path> getDaemonExecutable() {
|
||||
var base = getDaemonBasePath(OsType.getLocal()).orElseThrow();
|
||||
var debug = BeaconConfig.launchDaemonInDebugMode();
|
||||
Path executable;
|
||||
if (!debug) {
|
||||
executable = getDaemonExecutableInBaseDirectory(OsType.getLocal());
|
||||
} else {
|
||||
String scriptName = null;
|
||||
if (BeaconConfig.attachDebuggerToDaemon()) {
|
||||
scriptName = "xpiped_debug_attach";
|
||||
} else {
|
||||
scriptName = "xpiped_debug";
|
||||
}
|
||||
|
||||
if (System.getProperty("os.name").startsWith("Windows")) {
|
||||
scriptName = scriptName + ".bat";
|
||||
} else {
|
||||
scriptName = scriptName + ".sh";
|
||||
}
|
||||
|
||||
executable = Path.of("app", "scripts", scriptName);
|
||||
}
|
||||
|
||||
Path file = base.resolve(executable);
|
||||
if (Files.exists(file)) {
|
||||
return Optional.of(file);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
37
beacon/src/main/java/io/xpipe/beacon/NamedFunction.java
Normal file
37
beacon/src/main/java/io/xpipe/beacon/NamedFunction.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package io.xpipe.beacon;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.xpipe.beacon.exchange.NamedFunctionExchange;
|
||||
import io.xpipe.core.util.Proxyable;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Getter
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
public abstract class NamedFunction<T> {
|
||||
|
||||
@SneakyThrows
|
||||
public T call() {
|
||||
var proxyStore = Proxyable.getProxy(getProxyBase());
|
||||
if (proxyStore != null) {
|
||||
var client = BeaconClient.connectProxy(proxyStore);
|
||||
client.sendRequest(
|
||||
NamedFunctionExchange.Request.builder().function(this).build());
|
||||
NamedFunctionExchange.Response response = client.receiveResponse();
|
||||
return (T) response.getReturnValue();
|
||||
} else {
|
||||
return callLocal();
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
protected Object getProxyBase() {
|
||||
var first = Arrays.stream(getClass().getDeclaredFields()).findFirst().orElseThrow();
|
||||
first.setAccessible(true);
|
||||
return first.get(this);
|
||||
}
|
||||
|
||||
public abstract T callLocal();
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
package io.xpipe.beacon.exchange;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.xpipe.beacon.NamedFunction;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
|
@ -19,11 +18,7 @@ public class NamedFunctionExchange implements MessageExchange {
|
|||
@Builder
|
||||
@Value
|
||||
public static class Request implements RequestMessage {
|
||||
@NonNull
|
||||
String id;
|
||||
|
||||
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, property="type")
|
||||
@NonNull Object[] arguments;
|
||||
NamedFunction<?> function;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
|
|
|
@ -25,6 +25,7 @@ module io.xpipe.beacon {
|
|||
requires static lombok;
|
||||
|
||||
uses MessageExchange;
|
||||
uses io.xpipe.beacon.NamedFunction;
|
||||
|
||||
provides Module with BeaconJacksonModule;
|
||||
provides io.xpipe.beacon.exchange.MessageExchange with
|
||||
|
|
|
@ -18,6 +18,14 @@ public class FileNames {
|
|||
return normalize(joined);
|
||||
}
|
||||
|
||||
public static String getParent(String file) {
|
||||
return file.substring(0, file.length() - getFileName(file).length() - 1);
|
||||
}
|
||||
|
||||
public static boolean startsWith(String file, String start) {
|
||||
return normalize(file).startsWith(normalize(start));
|
||||
}
|
||||
|
||||
public static String normalize(String file) {
|
||||
var backslash = file.contains("\\");
|
||||
return backslash ? toWindows(file) : toUnix(file);
|
||||
|
|
|
@ -17,6 +17,12 @@ public interface ShellProcessControl extends ProcessControl {
|
|||
}
|
||||
}
|
||||
|
||||
default boolean executeBooleanSimpleCommand(String command) throws Exception {
|
||||
try (CommandProcessControl c = command(command).start()) {
|
||||
return c.discardAndCheckExit();
|
||||
}
|
||||
}
|
||||
|
||||
default String executeSimpleCommand(ShellType type, String command) throws Exception {
|
||||
return executeSimpleCommand(type.switchTo(command));
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public interface ShellType {
|
|||
|
||||
String createFileWriteCommand(String file);
|
||||
|
||||
List<String> createFileExistsCommand(String file);
|
||||
String createFileExistsCommand(String file);
|
||||
|
||||
Charset determineCharset(ShellProcessControl control) throws Exception;
|
||||
|
||||
|
|
|
@ -132,8 +132,8 @@ public class ShellTypes {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> createFileExistsCommand(String file) {
|
||||
return List.of("dir", "/a", file);
|
||||
public String createFileExistsCommand(String file) {
|
||||
return String.format("dir /a \"%s\"", file);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -263,8 +263,8 @@ public class ShellTypes {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> createFileExistsCommand(String file) {
|
||||
return List.of("cmd", "/c", "dir", "/a", file);
|
||||
public String createFileExistsCommand(String file) {
|
||||
return String.format("cmd /c dir /a \"%s\"", file);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -386,8 +386,8 @@ public class ShellTypes {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> createFileExistsCommand(String file) {
|
||||
return List.of("(", "test", "-f", file, "||", "test", "-d", file, ")");
|
||||
public String createFileExistsCommand(String file) {
|
||||
return String.format("test -f \"%s\" || test -d \"%s\"", file, file);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,7 +37,7 @@ public interface MachineStore extends FileSystemStore, ShellStore {
|
|||
|
||||
@Override
|
||||
public default boolean exists(String file) throws Exception {
|
||||
try (var pc = create().commandListFunction(proc -> proc.getShellType().createFileExistsCommand(proc.getOsType().normalizeFileName(file)))
|
||||
try (var pc = create().commandFunction(proc -> proc.getShellType().createFileExistsCommand(proc.getOsType().normalizeFileName(file)))
|
||||
.start()) {
|
||||
return pc.discardAndCheckExit();
|
||||
}
|
||||
|
|
21
core/src/main/java/io/xpipe/core/util/Proxyable.java
Normal file
21
core/src/main/java/io/xpipe/core/util/Proxyable.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package io.xpipe.core.util;
|
||||
|
||||
import io.xpipe.core.store.ShellStore;
|
||||
|
||||
public interface Proxyable {
|
||||
|
||||
public static ShellStore getProxy(Object base) {
|
||||
var proxy = base instanceof Proxyable p ? p.getProxy() : null;
|
||||
return ShellStore.isLocal(proxy) ? null : proxy;
|
||||
}
|
||||
|
||||
public static boolean isRemote(Object base) {
|
||||
if (base == null) {
|
||||
throw new IllegalArgumentException("Proxy base is null");
|
||||
}
|
||||
|
||||
return base instanceof Proxyable p && !ShellStore.isLocal(p.getProxy());
|
||||
}
|
||||
|
||||
ShellStore getProxy();
|
||||
}
|
|
@ -1,43 +1,56 @@
|
|||
package io.xpipe.core.util;
|
||||
|
||||
import io.xpipe.core.impl.FileNames;
|
||||
import io.xpipe.core.impl.LocalStore;
|
||||
import io.xpipe.core.process.CommandProcessControl;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.process.ShellProcessControl;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.io.IOException;
|
||||
|
||||
public class XPipeInstallation {
|
||||
|
||||
public static Optional<String> queryInstallationVersion(ShellProcessControl p) throws Exception {
|
||||
var executable = getInstallationExecutable(p);
|
||||
if (executable.isEmpty()) {
|
||||
return Optional.empty();
|
||||
public static String getInstallationBasePathForCLI(ShellProcessControl p, String cliExecutable) throws Exception {
|
||||
var defaultInstallation = getDefaultInstallationBasePath(p);
|
||||
if (p.getOsType().equals(OsType.LINUX) && cliExecutable.equals("/usr/bin/xpipe")) {
|
||||
return defaultInstallation;
|
||||
}
|
||||
|
||||
try (CommandProcessControl c = p.command(executable.get() + " version").start()) {
|
||||
return Optional.ofNullable(c.readOrThrow());
|
||||
if (FileNames.startsWith(cliExecutable, defaultInstallation)) {
|
||||
return defaultInstallation;
|
||||
}
|
||||
|
||||
return FileNames.getParent(FileNames.getParent(cliExecutable));
|
||||
}
|
||||
|
||||
public static String queryInstallationVersion(ShellProcessControl p, String exec) throws Exception {
|
||||
try (CommandProcessControl c = p.command(exec + " version").start()) {
|
||||
return c.readOrThrow();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean containsCompatibleInstallation(ShellProcessControl p, String version) throws Exception {
|
||||
var executable = getInstallationExecutable(p);
|
||||
public static boolean containsCompatibleDefaultInstallation(ShellProcessControl p, String version) throws Exception {
|
||||
var defaultBase = getDefaultInstallationBasePath(p);
|
||||
var executable = getInstallationExecutable(p, defaultBase);
|
||||
if (executable.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try (CommandProcessControl c = p.command(executable.get() + " version").start()) {
|
||||
try (CommandProcessControl c = p.command(executable + " version").start()) {
|
||||
return c.readOrThrow().equals(version);
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<String> getInstallationExecutable(ShellProcessControl p) throws Exception {
|
||||
var installation = getDefaultInstallationBasePath(p);
|
||||
var executable = getDaemonExecutableInInstallationDirectory(p.getOsType());
|
||||
public static String getInstallationExecutable(ShellProcessControl p, String installation) throws Exception {
|
||||
var executable = getDaemonExecutablePath(p.getOsType());
|
||||
var file = FileNames.join(installation, executable);
|
||||
try (CommandProcessControl c =
|
||||
p.command(p.getShellType().createFileExistsCommand(file)).start()) {
|
||||
return c.startAndCheckExit() ? Optional.of(file) : Optional.empty();
|
||||
if (!c.startAndCheckExit()) {
|
||||
throw new IOException("File not found: " + file);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,20 +63,57 @@ public class XPipeInstallation {
|
|||
}
|
||||
}
|
||||
|
||||
public static String getDefaultInstallationBasePath(ShellProcessControl p) throws Exception {
|
||||
if (p.getOsType().equals(OsType.WINDOWS)) {
|
||||
var base = p.executeSimpleCommand(p.getShellType().getPrintVariableCommand("LOCALAPPDATA"));
|
||||
return FileNames.join(base, "X-Pipe");
|
||||
} else {
|
||||
return "/opt/xpipe";
|
||||
public static String getDefaultInstallationBasePath() throws Exception {
|
||||
try (ShellProcessControl pc = new LocalStore().create().start()) {
|
||||
return getDefaultInstallationBasePath(pc);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getDaemonExecutableInInstallationDirectory(OsType type) {
|
||||
if (type.equals(OsType.WINDOWS)) {
|
||||
return FileNames.join("app", "runtime", "bin", "xpiped.bat");
|
||||
public static String getDefaultInstallationBasePath(ShellProcessControl p) throws Exception {
|
||||
var customHome = p.executeSimpleCommand(p.getShellType().getPrintVariableCommand("XPIPE_HOME"));
|
||||
if (!customHome.isEmpty()) {
|
||||
return customHome;
|
||||
}
|
||||
|
||||
String path = null;
|
||||
if (p.getOsType().equals(OsType.WINDOWS)) {
|
||||
var base = p.executeSimpleCommand(p.getShellType().getPrintVariableCommand("LOCALAPPDATA"));
|
||||
path = FileNames.join(base, "X-Pipe");
|
||||
} else {
|
||||
return FileNames.join("app/bin/xpiped");
|
||||
path = "/opt/xpipe";
|
||||
}
|
||||
|
||||
try (CommandProcessControl c =
|
||||
p.command(p.getShellType().createFileExistsCommand(path)).start()) {
|
||||
if (!c.discardAndCheckExit()) {
|
||||
throw new IOException("Installation not found in " + path);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static String getDaemonDebugScriptPath(OsType type) {
|
||||
if (type.equals(OsType.WINDOWS)) {
|
||||
return FileNames.join("app", "scripts", "xpiped_debug.bat");
|
||||
} else {
|
||||
return FileNames.join("app", "scripts", "xpiped_debug.sh");
|
||||
}
|
||||
}
|
||||
|
||||
public static String getDaemonDebugAttachScriptPath(OsType type) {
|
||||
if (type.equals(OsType.WINDOWS)) {
|
||||
return FileNames.join("app", "scripts", "xpiped_debug_attach.bat");
|
||||
} else {
|
||||
return FileNames.join("app", "scripts", "xpiped_debug_attach.sh");
|
||||
}
|
||||
}
|
||||
|
||||
public static String getDaemonExecutablePath(OsType type) {
|
||||
if (type.equals(OsType.WINDOWS)) {
|
||||
return FileNames.join("app", "xpiped.exe");
|
||||
} else {
|
||||
return FileNames.join("app", "bin", "xpiped");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
package io.xpipe.extension;
|
||||
|
||||
import io.xpipe.beacon.exchange.NamedFunctionExchange;
|
||||
import io.xpipe.extension.event.ErrorEvent;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
@Getter
|
||||
public class NamedFunction {
|
||||
|
||||
public static final List<NamedFunction> ALL = new ArrayList<>();
|
||||
|
||||
public static void init(ModuleLayer layer) {
|
||||
if (ALL.size() == 0) {
|
||||
ALL.addAll(ServiceLoader.load(layer, NamedFunction.class).stream()
|
||||
.map(p -> p.get())
|
||||
.toList());
|
||||
}
|
||||
}
|
||||
|
||||
public static NamedFunction get(String id) {
|
||||
return ALL.stream()
|
||||
.filter(namedFunction -> namedFunction.id.equalsIgnoreCase(id))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
public static <T> T callLocal(String id, Object... args) {
|
||||
return get(id).callLocal(args);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static <T> T callRemote(String id, Object... args) {
|
||||
var proxy = XPipeProxy.getProxy(args[0]);
|
||||
var client = XPipeProxy.connect(proxy);
|
||||
client.sendRequest(
|
||||
NamedFunctionExchange.Request.builder().id(id).arguments(args).build());
|
||||
NamedFunctionExchange.Response response = client.receiveResponse();
|
||||
return (T) response.getReturnValue();
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static <T> T call(Class<? extends NamedFunction> clazz, Object... args) {
|
||||
var base = args[0];
|
||||
var proxy = XPipeProxy.getProxy(base);
|
||||
if (proxy != null) {
|
||||
return callRemote(clazz.getDeclaredConstructor().newInstance().getId(), args);
|
||||
} else {
|
||||
return callLocal(clazz.getDeclaredConstructor().newInstance().getId(), args);
|
||||
}
|
||||
}
|
||||
|
||||
private final String id;
|
||||
private final Method method;
|
||||
|
||||
public NamedFunction(String id, Method method) {
|
||||
this.id = id;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public NamedFunction(String id, Class<?> clazz) {
|
||||
this.id = id;
|
||||
this.method = Arrays.stream(clazz.getDeclaredMethods())
|
||||
.filter(method1 -> method1.getName().equals(id))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
public <T> T callLocal(Object... args) {
|
||||
try {
|
||||
return (T) method.invoke(null, args);
|
||||
} catch (Throwable ex) {
|
||||
ErrorEvent.fromThrowable(ex).handle();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package io.xpipe.extension;
|
||||
|
||||
import io.xpipe.core.store.ShellStore;
|
||||
|
||||
public interface Proxyable {
|
||||
|
||||
ShellStore getProxy();
|
||||
}
|
|
@ -2,9 +2,9 @@ package io.xpipe.extension;
|
|||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import io.xpipe.api.connector.XPipeConnection;
|
||||
import io.xpipe.beacon.BeaconClient;
|
||||
import io.xpipe.api.connector.XPipeApiConnection;
|
||||
import io.xpipe.beacon.exchange.ProxyReadConnectionExchange;
|
||||
import io.xpipe.core.impl.FileNames;
|
||||
import io.xpipe.core.impl.InputStreamStore;
|
||||
import io.xpipe.core.process.ShellProcessControl;
|
||||
import io.xpipe.core.source.DataSource;
|
||||
|
@ -21,18 +21,8 @@ import java.util.function.Function;
|
|||
|
||||
public class XPipeProxy {
|
||||
|
||||
public static BeaconClient connect(ShellStore proxy) throws Exception {
|
||||
var control = proxy.create().start();
|
||||
var command = control.command("xpipe beacon").start();
|
||||
return BeaconClient.connectGateway(
|
||||
command,
|
||||
BeaconClient.GatewayClientInformation.builder()
|
||||
.version(XPipeDaemon.getInstance().getVersion())
|
||||
.build());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private static DataSource<?> downstreamTransform(DataSource<?> input, ShellStore proxy) {
|
||||
private static DataSource<?> downstreamTransform(DataSource<?> input, ShellStore proxy) {
|
||||
var proxyNode = JacksonMapper.newMapper().valueToTree(proxy);
|
||||
var inputNode = JacksonMapper.newMapper().valueToTree(input);
|
||||
var localNode = JacksonMapper.newMapper().valueToTree(ShellStore.local());
|
||||
|
@ -40,8 +30,7 @@ public class XPipeProxy {
|
|||
return JacksonMapper.newMapper().treeToValue(inputNode, DataSource.class);
|
||||
}
|
||||
|
||||
private static JsonNode replace(
|
||||
JsonNode node, Function<JsonNode, Optional<JsonNode>> function) {
|
||||
private static JsonNode replace(JsonNode node, Function<JsonNode, Optional<JsonNode>> function) {
|
||||
var value = function.apply(node);
|
||||
if (value.isPresent()) {
|
||||
return value.get();
|
||||
|
@ -63,8 +52,10 @@ public class XPipeProxy {
|
|||
|
||||
public static <T extends DataSourceReadConnection> T remoteReadConnection(DataSource<?> source, ShellStore proxy) {
|
||||
var downstream = downstreamTransform(source, proxy);
|
||||
return (T) XPipeConnection.execute(con -> {
|
||||
con.sendRequest(ProxyReadConnectionExchange.Request.builder().source(downstream).build());
|
||||
return (T) XPipeApiConnection.execute(con -> {
|
||||
con.sendRequest(ProxyReadConnectionExchange.Request.builder()
|
||||
.source(downstream)
|
||||
.build());
|
||||
con.receiveResponse();
|
||||
var inputSource = DataSource.createInternalDataSource(
|
||||
source.determineInfo().getType(), new InputStreamStore(con.receiveBody()));
|
||||
|
@ -72,23 +63,18 @@ public class XPipeProxy {
|
|||
});
|
||||
}
|
||||
|
||||
public static ShellStore getProxy(Object base) {
|
||||
return base instanceof Proxyable p ? p.getProxy() : null;
|
||||
}
|
||||
|
||||
public static boolean isRemote(Object base) {
|
||||
return base instanceof Proxyable p && !ShellStore.isLocal(p.getProxy());
|
||||
}
|
||||
|
||||
public static void checkSupport(ShellStore store) throws Exception {
|
||||
var version = XPipeDaemon.getInstance().getVersion();
|
||||
try (ShellProcessControl s = store.create().start()) {
|
||||
var installationVersion = XPipeInstallation.queryInstallationVersion(s);
|
||||
if (installationVersion.isEmpty()) {
|
||||
var defaultInstallationExecutable = FileNames.join(
|
||||
XPipeInstallation.getDefaultInstallationBasePath(s),
|
||||
XPipeInstallation.getDaemonExecutablePath(s.getOsType()));
|
||||
if (!s.executeBooleanSimpleCommand(s.getShellType().createFileExistsCommand(defaultInstallationExecutable))) {
|
||||
throw new IOException(I18n.get("noInstallationFound"));
|
||||
}
|
||||
|
||||
if (!version.equals(installationVersion.get())) {
|
||||
var installationVersion = XPipeInstallation.queryInstallationVersion(s, defaultInstallationExecutable);
|
||||
if (!version.equals(installationVersion)) {
|
||||
throw new IOException(I18n.get("versionMismatch", version, installationVersion));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ public class XPipeServiceProviders {
|
|||
|
||||
SupportedApplicationProviders.loadAll(layer);
|
||||
PrefsProviders.init(layer);
|
||||
NamedFunction.init(layer);
|
||||
TrackEvent.info("Finished loading extension providers");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.extension.util;
|
||||
|
||||
import io.xpipe.api.DataSource;
|
||||
import io.xpipe.api.util.XPipeDaemonController;
|
||||
import io.xpipe.beacon.BeaconDaemonController;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import io.xpipe.core.util.JacksonMapper;
|
||||
import io.xpipe.extension.XPipeServiceProviders;
|
||||
|
@ -26,11 +26,11 @@ public class DaemonExtensionTest extends ExtensionTest {
|
|||
public static void setup() throws Exception {
|
||||
JacksonMapper.initModularized(ModuleLayer.boot());
|
||||
XPipeServiceProviders.load(ModuleLayer.boot());
|
||||
XPipeDaemonController.start();
|
||||
BeaconDaemonController.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void teardown() throws Exception {
|
||||
XPipeDaemonController.stop();
|
||||
BeaconDaemonController.stop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import io.xpipe.beacon.NamedFunction;
|
||||
import io.xpipe.extension.DataSourceProvider;
|
||||
import io.xpipe.extension.DataStoreActionProvider;
|
||||
import io.xpipe.extension.SupportedApplicationProvider;
|
||||
|
@ -40,5 +41,5 @@ open module io.xpipe.extension {
|
|||
uses XPipeDaemon;
|
||||
uses io.xpipe.extension.Cache;
|
||||
uses io.xpipe.extension.DataSourceActionProvider;
|
||||
uses io.xpipe.extension.NamedFunction;
|
||||
uses NamedFunction;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue