More work on proxies

This commit is contained in:
Christopher Schnick 2022-11-27 21:39:41 +01:00
parent de70b0d5b0
commit 803ff2ccf2
9 changed files with 107 additions and 35 deletions

View file

@ -11,7 +11,6 @@ import com.fasterxml.jackson.databind.node.TextNode;
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;
@ -107,16 +106,10 @@ public class BeaconClient implements AutoCloseable {
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;
command.discardErr();
return new BeaconClient(() -> {
command.close();
}, command.getStdout(), command.getStdin());
}
public static Optional<BeaconClient> tryConnect(ClientInformation information) {

View file

@ -16,6 +16,14 @@ public class BeaconConfig {
private static final String EXEC_DEBUG_PROP = "io.xpipe.beacon.printDaemonOutput";
private static final String EXEC_PROCESS_PROP = "io.xpipe.beacon.customDaemonCommand";
private static final String DAEMON_ARGUMENTS_PROP = "io.xpipe.beacon.daemonArgs";
private static final String LOCAL_PROXY_PROP = "io.xpipe.beacon.localProxy";
public static boolean localProxy() {
if (System.getProperty(LOCAL_PROXY_PROP) != null) {
return Boolean.parseBoolean(System.getProperty(LOCAL_PROXY_PROP));
}
return false;
}
public static boolean printMessages() {
if (System.getProperty(PRINT_MESSAGES_PROPERTY) != null) {

View file

@ -1,17 +1,70 @@
package io.xpipe.beacon;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import io.xpipe.beacon.exchange.NamedFunctionExchange;
import io.xpipe.core.util.Proxyable;
import io.xpipe.core.util.JacksonMapper;
import lombok.Getter;
import lombok.SneakyThrows;
import java.io.IOException;
import java.util.Arrays;
@Getter
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public abstract class NamedFunction<T> {
private static ModuleLayer layer;
public static void init(ModuleLayer l) {
layer = l;
}
public static class Serializer extends StdSerializer<NamedFunction> {
protected Serializer() {
super(NamedFunction.class);
}
@Override
public void serialize(NamedFunction value, JsonGenerator gen, SerializerProvider provider) throws IOException {
var node = (ObjectNode) JacksonMapper.getDefault().valueToTree(value);
node.set("module", new TextNode(value.getClass().getModule().getName()));
node.set("class", new TextNode(value.getClass().getName()));
gen.writeTree(node);
}
}
public static class Deserializer extends StdDeserializer<NamedFunction<?>> {
protected Deserializer() {
super(NamedFunction.class);
}
@Override
@SneakyThrows
public NamedFunction<?> deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JacksonException {
var tree = (ObjectNode) JacksonMapper.getDefault().readTree(p);
var moduleReference = tree.remove("module").asText();
var classReference = tree.remove("class").asText();
var module = layer.findModule(moduleReference).orElseThrow();
var targetClass = Class.forName(module, classReference);
if (targetClass == null) {
throw new IllegalArgumentException("Named function class not found: " + classReference);
}
return (NamedFunction<?>) JacksonMapper.getDefault().treeToValue(tree, targetClass);
}
}
@SneakyThrows
public T call() {
var proxyStore = Proxyable.getProxy(getProxyBase());

View file

@ -1,4 +1,4 @@
package io.xpipe.core.util;
package io.xpipe.beacon;
import io.xpipe.core.store.ShellStore;
@ -6,7 +6,7 @@ public interface Proxyable {
public static ShellStore getProxy(Object base) {
var proxy = base instanceof Proxyable p ? p.getProxy() : null;
return ShellStore.isLocal(proxy) ? null : proxy;
return ShellStore.isLocal(proxy) ? (BeaconConfig.localProxy() ? proxy : null) : proxy;
}
public static boolean isRemote(Object base) {

View file

@ -1,5 +1,7 @@
package io.xpipe.beacon.exchange;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.xpipe.beacon.NamedFunction;
import io.xpipe.beacon.RequestMessage;
import io.xpipe.beacon.ResponseMessage;
@ -18,6 +20,9 @@ public class NamedFunctionExchange implements MessageExchange {
@Builder
@Value
public static class Request implements RequestMessage {
@JsonSerialize(using = NamedFunction.Serializer.class, as = NamedFunction.class)
@JsonDeserialize(using = NamedFunction.Deserializer.class, as = NamedFunction.class)
NamedFunction<?> function;
}

View file

@ -0,0 +1,26 @@
package io.xpipe.core.impl;
import io.xpipe.core.process.ShellProcessControl;
import java.util.ServiceLoader;
public abstract class LocalProcessControlProvider {
private static LocalProcessControlProvider INSTANCE;
public static void init(ModuleLayer layer) {
INSTANCE = layer != null
? ServiceLoader.load(layer, LocalProcessControlProvider.class)
.findFirst()
.orElseThrow()
: ServiceLoader.load(LocalProcessControlProvider.class)
.findFirst()
.orElseThrow();
}
public static ShellProcessControl create() {
return INSTANCE.createProcessControl();
}
public abstract ShellProcessControl createProcessControl();
}

View file

@ -10,7 +10,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ServiceLoader;
@JsonTypeName("local")
public class LocalStore extends JacksonizedValue implements FileSystemStore, MachineStore {
@ -51,18 +50,4 @@ public class LocalStore extends JacksonizedValue implements FileSystemStore, Mac
return LocalProcessControlProvider.create();
}
public static abstract class LocalProcessControlProvider {
private static LocalProcessControlProvider INSTANCE;
public static void init(ModuleLayer layer) {
INSTANCE = ServiceLoader.load(layer, LocalProcessControlProvider.class).findFirst().orElseThrow();
}
public static ShellProcessControl create() {
return INSTANCE.createProcessControl();
}
public abstract ShellProcessControl createProcessControl();
}
}

View file

@ -1,4 +1,4 @@
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.impl.LocalProcessControlProvider;
import io.xpipe.core.source.WriteMode;
import io.xpipe.core.util.CoreJacksonModule;
@ -24,7 +24,7 @@ open module io.xpipe.core {
uses com.fasterxml.jackson.databind.Module;
uses io.xpipe.core.source.WriteMode;
uses LocalStore.LocalProcessControlProvider;
uses LocalProcessControlProvider;
provides WriteMode with WriteMode.Replace, WriteMode.Append, WriteMode.Prepend;
provides com.fasterxml.jackson.databind.Module with

View file

@ -1,7 +1,8 @@
package io.xpipe.extension;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.beacon.NamedFunction;
import io.xpipe.core.impl.LocalProcessControlProvider;
import io.xpipe.core.util.JacksonMapper;
import io.xpipe.extension.event.TrackEvent;
import io.xpipe.extension.prefs.PrefsProviders;
@ -9,7 +10,7 @@ import io.xpipe.extension.prefs.PrefsProviders;
public class XPipeServiceProviders {
public static void load(ModuleLayer layer) {
LocalStore.LocalProcessControlProvider.init(layer);
LocalProcessControlProvider.init(layer);
TrackEvent.info("Loading extension providers ...");
DataSourceProviders.init(layer);
@ -35,6 +36,7 @@ public class XPipeServiceProviders {
SupportedApplicationProviders.loadAll(layer);
PrefsProviders.init(layer);
NamedFunction.init(layer);
TrackEvent.info("Finished loading extension providers");
}
}