This commit is contained in:
crschnick
2026-05-29 02:15:42 +00:00
parent af533b5988
commit 3ceead048e
441 changed files with 2355 additions and 2839 deletions
+6 -5
View File
@@ -19,9 +19,6 @@ configurations {
}
dependencies {
api project(':core')
api project(':beacon')
compileOnly 'org.hamcrest:hamcrest:3.0'
compileOnly 'org.junit.jupiter:junit-jupiter-api:5.14.2'
compileOnly 'org.junit.jupiter:junit-jupiter-params:5.14.2'
@@ -97,7 +94,7 @@ jar {
application {
mainModule = groupName + '.app'
mainClass = groupName + '.app.Main'
applicationDefaultJvmArgs = jvmRunArgs
applicationDefaultJvmArgs = daemonJvmRunArgs
}
run {
@@ -123,6 +120,10 @@ run {
def exts = files(project.allExtensions.stream().map(p -> p.getTasksByName('jar', true)[0].outputs.files.singleFile).toList())
classpath += exts
def cli = project(':cli').getTasksByName('jar', true)[0].outputs.files.singleFile
classpath += files(cli)
dependsOn(project(':cli').getTasksByName('jar', true)[0])
dependsOn(project.allExtensions.stream().map(p -> p.getTasksByName('jar', true)[0]).toList())
}
@@ -132,7 +133,7 @@ tasks.register('runAttachedDebugger', JavaExec) {
mainModule = groupName + '.app'
mainClass = groupName + '.app.Main'
modularity.inferModulePath = true
jvmArgs += jvmRunArgs
jvmArgs += daemonJvmRunArgs
jvmArgs += List.of(
"-javaagent:${System.getProperty("user.home")}/.attachme/attachme-agent-1.2.9.jar=port:7857,host:localhost".toString(),
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:0"
+2 -8
View File
@@ -13,14 +13,8 @@ public class Main {
return;
}
// Since this is not marked as a console application, it will not print anything when you run it in a console on
// Windows
if (args.length == 1 && args[0].equals("--help")) {
System.out.printf("""
The daemon executable %s does not accept any command-line arguments.
For a reference on how to use xpipe from the command-line, take a look at https://docs.xpipe.io/cli.
%n""", AppNames.ofCurrent().getExecutableName());
if (args.length == 1 && (args[0].equals("--help") || args[0].equals("help"))) {
System.out.println("For a reference on how to use xpipe from the command-line, take a look at https://docs.xpipe.io/cli");
return;
}
@@ -4,8 +4,8 @@ import io.xpipe.app.ext.DataStore;
import io.xpipe.app.hub.action.*;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.core.JacksonMapper;
import io.xpipe.core.UuidHelper;
import io.xpipe.app.util.JacksonMapper;
import io.xpipe.app.util.UuidHelper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
@@ -2,7 +2,7 @@ package io.xpipe.app.action;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.core.ModuleLayerLoader;
import io.xpipe.app.util.ModuleLayerLoader;
import java.util.*;
@@ -59,5 +59,10 @@ public interface ActionProvider {
.map(p -> p.get())
.toList());
}
@Override
public boolean initForCli() {
return false;
}
}
}
@@ -1,7 +1,7 @@
package io.xpipe.app.action;
import io.xpipe.core.JacksonMapper;
import io.xpipe.core.SecretValue;
import io.xpipe.app.util.JacksonMapper;
import io.xpipe.app.util.SecretValue;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
@@ -2,8 +2,8 @@ package io.xpipe.app.action;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.DataStoreFormatter;
import io.xpipe.core.JacksonMapper;
import io.xpipe.core.UuidHelper;
import io.xpipe.app.util.JacksonMapper;
import io.xpipe.app.util.UuidHelper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -2,7 +2,6 @@ package io.xpipe.app.beacon;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.beacon.BeaconClientException;
import lombok.Value;
@@ -2,13 +2,12 @@ package io.xpipe.app.beacon;
import io.xpipe.app.beacon.mcp.AppMcpServer;
import io.xpipe.app.core.AppLocalTemp;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.DocumentationLink;
import io.xpipe.beacon.BeaconConfig;
import io.xpipe.beacon.BeaconInterface;
import io.xpipe.core.OsType;
import io.xpipe.app.util.OsType;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
@@ -56,7 +55,8 @@ public class AppBeaconServer {
public static void init() {
try {
INSTANCE = new AppBeaconServer(BeaconConfig.getUsedPort());
// We already queried the beacon port at this point, so this will always work
INSTANCE = new AppBeaconServer(AppProperties.get().queryEffectiveBeaconPort(false).orElseThrow());
INSTANCE.initAuthSecret();
INSTANCE.start();
TrackEvent.withInfo("Started http server")
@@ -111,7 +111,7 @@ public class AppBeaconServer {
}
private void initAuthSecret() throws IOException {
var file = BeaconConfig.getLocalBeaconAuthFile();
var file = AppProperties.get().getBeaconAuthFile();
// Create and set temp dir permissions for Linux
AppLocalTemp.getLocalTempDataDirectory();
@@ -122,13 +122,13 @@ public class AppBeaconServer {
}
localAuthSecret = id;
var lockFile = BeaconConfig.getLocalBeaconLockFile();
var lockFile = AppProperties.get().getBeaconLockFile();
localLockFileChannel = new RandomAccessFile(lockFile.toFile(), "rw").getChannel();
localLockFileLock = localLockFileChannel.tryLock();
}
private void deleteAuthSecret() {
var file = BeaconConfig.getLocalBeaconAuthFile();
var file = AppProperties.get().getBeaconAuthFile();
try {
Files.delete(file);
localLockFileLock.release();
@@ -1,4 +1,4 @@
package io.xpipe.beacon;
package io.xpipe.app.beacon;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
@@ -1,7 +1,7 @@
package io.xpipe.beacon;
package io.xpipe.app.beacon;
import io.xpipe.beacon.api.HandshakeExchange;
import io.xpipe.core.JacksonMapper;
import io.xpipe.app.beacon.api.HandshakeExchange;
import io.xpipe.app.util.JacksonMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.SneakyThrows;
@@ -12,10 +12,20 @@ import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
public class BeaconClient {
private static final String PRINT_MESSAGES_PROPERTY = "io.xpipe.beacon.printMessages";
private static boolean printMessages() {
if (System.getProperty(PRINT_MESSAGES_PROPERTY) != null) {
return Boolean.parseBoolean(System.getProperty(PRINT_MESSAGES_PROPERTY));
}
return false;
}
private final int port;
private String token;
@@ -23,9 +33,9 @@ public class BeaconClient {
this.port = port;
}
public static BeaconClient establishConnection(int port, BeaconClientInformation information) throws Exception {
public static BeaconClient establishConnection(int port, BeaconClientInformation information, Path authFile) throws Exception {
var client = new BeaconClient(port);
var auth = Files.readString(BeaconConfig.getLocalBeaconAuthFile());
var auth = Files.readString(authFile);
HandshakeExchange.Response response = client.performRequest(HandshakeExchange.Request.builder()
.client(information)
.auth(BeaconAuthMethod.Local.builder().authFileContent(auth).build())
@@ -34,19 +44,11 @@ public class BeaconClient {
return client;
}
public static Optional<BeaconClient> tryEstablishConnection(int port, BeaconClientInformation information) {
try {
return Optional.of(establishConnection(port, information));
} catch (Exception ex) {
return Optional.empty();
}
}
@SuppressWarnings("unchecked")
public <RES> RES performRequest(BeaconInterface<?> prov, String rawNode)
throws BeaconConnectorException, BeaconClientException, BeaconServerException {
var content = rawNode;
if (BeaconConfig.printMessages()) {
if (printMessages()) {
System.out.println("Sending raw request:");
System.out.println(content);
}
@@ -70,7 +72,7 @@ public class BeaconClient {
throw new BeaconConnectorException("Couldn't send request", ex);
}
if (BeaconConfig.printMessages()) {
if (printMessages()) {
System.out.println("Received raw response:");
System.out.println(response.body());
}
@@ -117,7 +119,7 @@ public class BeaconClient {
if (prov.isEmpty()) {
throw new IllegalArgumentException("Unknown request class " + req.getClass());
}
if (BeaconConfig.printMessages()) {
if (printMessages()) {
System.out.println(
"Sending request to server of type " + req.getClass().getName());
}
@@ -1,4 +1,4 @@
package io.xpipe.beacon;
package io.xpipe.app.beacon;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -1,4 +1,4 @@
package io.xpipe.beacon;
package io.xpipe.app.beacon;
/**
* Indicates that a client request was invalid.
@@ -1,4 +1,4 @@
package io.xpipe.beacon;
package io.xpipe.app.beacon;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
@@ -1,4 +1,4 @@
package io.xpipe.beacon;
package io.xpipe.app.beacon;
/**
* Indicates that a connection error occurred.
@@ -1,6 +1,6 @@
package io.xpipe.beacon;
package io.xpipe.app.beacon;
import io.xpipe.core.ModuleLayerLoader;
import io.xpipe.app.util.ModuleLayerLoader;
import com.sun.net.httpserver.HttpExchange;
import lombok.SneakyThrows;
@@ -31,16 +31,14 @@ public abstract class BeaconInterface<T> {
@SuppressWarnings("unchecked")
@SneakyThrows
public Class<T> getRequestClass() {
var c = getClass().getSuperclass();
var name = (c.getSuperclass().equals(BeaconInterface.class) ? c : getClass()).getName() + "$Request";
var name = getClass().getName() + "$Request";
return (Class<T>) Class.forName(name);
}
@SuppressWarnings("unchecked")
@SneakyThrows
public Class<T> getResponseClass() {
var c = getClass().getSuperclass();
var name = (c.getSuperclass().equals(BeaconInterface.class) ? c : getClass()).getName() + "$Response";
var name = getClass().getName() + "$Response";
return (Class<T>) Class.forName(name);
}
@@ -78,17 +76,16 @@ public abstract class BeaconInterface<T> {
@Override
public void init(ModuleLayer layer) {
var services = layer != null
? ServiceLoader.load(layer, BeaconInterface.class)
: ServiceLoader.load(BeaconInterface.class);
var services = ServiceLoader.load(layer, BeaconInterface.class);
ALL = services.stream()
.map(ServiceLoader.Provider::get)
.map(beaconInterface -> (BeaconInterface<?>) beaconInterface)
.collect(Collectors.toList());
// Remove parent classes
ALL.removeIf(beaconInterface -> ALL.stream()
.anyMatch(other -> !other.equals(beaconInterface)
&& beaconInterface.getClass().isAssignableFrom(other.getClass())));
}
@Override
public boolean initForCli() {
return true;
}
}
}
@@ -5,8 +5,7 @@ import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.beacon.*;
import io.xpipe.core.JacksonMapper;
import io.xpipe.app.util.JacksonMapper;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
@@ -1,6 +1,6 @@
package io.xpipe.beacon;
package io.xpipe.app.beacon;
import io.xpipe.beacon.api.DaemonStopExchange;
import io.xpipe.app.beacon.api.DaemonStopExchange;
import lombok.SneakyThrows;
@@ -1,4 +1,4 @@
package io.xpipe.beacon;
package io.xpipe.app.beacon;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -1,4 +1,4 @@
package io.xpipe.beacon;
package io.xpipe.app.beacon;
/**
* Indicates that an internal server error occurred.
@@ -1,7 +1,5 @@
package io.xpipe.app.beacon;
import io.xpipe.beacon.BeaconClientInformation;
import lombok.Value;
@Value
@@ -2,7 +2,6 @@ package io.xpipe.app.beacon;
import io.xpipe.app.core.AppLocalTemp;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.beacon.BeaconClientException;
import org.apache.commons.io.FileUtils;
@@ -1,14 +1,23 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.fasterxml.jackson.databind.JsonNode;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.action.ActionJacksonMapper;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.core.AppCache;
import io.xpipe.app.core.window.AppDialog;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.ActionExchange;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import com.sun.net.httpserver.HttpExchange;
public class ActionExchange extends BeaconInterface<ActionExchange.Request> {
public class ActionExchangeImpl extends ActionExchange {
@Override
public String getPath() {
return "/action";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws Exception {
@@ -37,4 +46,19 @@ public class ActionExchangeImpl extends ActionExchange {
}
return r;
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
JsonNode action;
boolean confirm;
}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -1,5 +1,8 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.core.AppCache;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.core.window.AppDialog;
@@ -8,18 +11,31 @@ import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.app.secret.SecretManager;
import io.xpipe.app.secret.SecretQueryState;
import io.xpipe.app.terminal.TerminalView;
import io.xpipe.app.util.*;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.AskpassExchange;
import io.xpipe.core.InPlaceSecretValue;
import io.xpipe.app.util.AskpassAlert;
import io.xpipe.app.util.GlobalTimer;
import io.xpipe.app.util.InPlaceSecretValue;
import io.xpipe.app.util.SecretValue;
import javafx.beans.property.SimpleStringProperty;
import com.sun.net.httpserver.HttpExchange;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.time.Duration;
import java.util.UUID;
public class AskpassExchangeImpl extends AskpassExchange {
public class AskpassExchange extends BeaconInterface<AskpassExchange.Request> {
@Override
public boolean acceptInShutdown() {
return true;
}
@Override
public String getPath() {
return "/askpass";
}
@Override
public boolean requiresCompletedStartup() {
@@ -106,4 +122,25 @@ public class AskpassExchangeImpl extends AskpassExchange {
}
TerminalView.focus(term.get());
}
@Jacksonized
@Builder
@Value
public static class Request {
long pid;
UUID secretId;
UUID request;
String prompt;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
SecretValue value;
}
}
@@ -1,13 +1,24 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreCategory;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.CategoryAddExchange;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import com.sun.net.httpserver.HttpExchange;
import java.util.UUID;
public class CategoryAddExchangeImpl extends CategoryAddExchange {
public class CategoryAddExchange extends BeaconInterface<CategoryAddExchange.Request> {
@Override
public String getPath() {
return "/category/add";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws Throwable {
@@ -32,4 +43,23 @@ public class CategoryAddExchangeImpl extends CategoryAddExchange {
public Object getSynchronizationObject() {
return DataStorage.get();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
String name;
@NonNull
UUID parent;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
UUID category;
}
}
@@ -1,16 +1,29 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.CategoryInfoExchange;
import io.xpipe.core.JacksonMapper;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.JacksonMapper;
import io.xpipe.app.util.StorePath;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class CategoryInfoExchangeImpl extends CategoryInfoExchange {
public class CategoryInfoExchange extends BeaconInterface<CategoryInfoExchange.Request> {
@Override
public String getPath() {
return "/category/info";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException {
@@ -39,4 +52,42 @@ public class CategoryInfoExchangeImpl extends CategoryInfoExchange {
public Object getSynchronizationObject() {
return DataStorage.get();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
List<UUID> categories;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
List<@NonNull InfoResponse> infos;
}
@Jacksonized
@Builder
@Value
public static class InfoResponse {
@NonNull
UUID category;
UUID parentCategory;
@NonNull
StorePath name;
@NonNull
Instant lastUsed;
@NonNull
Instant lastModified;
@NonNull
JsonNode config;
}
}
@@ -0,0 +1,51 @@
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStorageQuery;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.List;
import java.util.UUID;
public class CategoryQueryExchange extends BeaconInterface<CategoryQueryExchange.Request> {
@Override
public String getPath() {
return "/category/query";
}
@Override
public Object handle(HttpExchange exchange, Request msg) {
var found = DataStorageQuery.queryCategory(msg.getFilter());
return Response.builder()
.found(found.stream().map(entry -> entry.getUuid()).toList())
.build();
}
@Override
public Object getSynchronizationObject() {
return DataStorage.get();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
String filter;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
List<@NonNull UUID> found;
}
}
@@ -1,16 +1,26 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreCategory;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.CategoryRemoveExchange;
import com.sun.net.httpserver.HttpExchange;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class CategoryRemoveExchangeImpl extends CategoryRemoveExchange {
public class CategoryRemoveExchange extends BeaconInterface<CategoryRemoveExchange.Request> {
@Override
public String getPath() {
return "/category/remove";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException {
@@ -38,4 +48,21 @@ public class CategoryRemoveExchangeImpl extends CategoryRemoveExchange {
public Object getSynchronizationObject() {
return DataStorage.get();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
List<UUID> categories;
boolean removeChildrenCategories;
boolean removeContents;
}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -1,17 +1,29 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import com.fasterxml.jackson.databind.JsonNode;
import io.xpipe.app.ext.DataStore;
import io.xpipe.app.ext.ValidationException;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.ConnectionAddExchange;
import io.xpipe.core.JacksonMapper;
import io.xpipe.app.util.JacksonMapper;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import com.sun.net.httpserver.HttpExchange;
import java.util.UUID;
public class ConnectionAddExchangeImpl extends ConnectionAddExchange {
public class ConnectionAddExchange extends BeaconInterface<ConnectionAddExchange.Request> {
@Override
public String getPath() {
return "/connection/add";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws Throwable {
@@ -76,4 +88,28 @@ public class ConnectionAddExchangeImpl extends ConnectionAddExchange {
public Object getSynchronizationObject() {
return DataStorage.get();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
String name;
@NonNull
JsonNode data;
@NonNull
Boolean validate;
UUID category;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
UUID connection;
}
}
@@ -1,18 +1,30 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.ConnectionInfoExchange;
import io.xpipe.core.StorePath;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.StorePath;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import org.apache.commons.lang3.ClassUtils;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
public class ConnectionInfoExchangeImpl extends ConnectionInfoExchange {
public class ConnectionInfoExchange extends BeaconInterface<ConnectionInfoExchange.Request> {
@Override
public String getPath() {
return "/connection/info";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException {
@@ -60,4 +72,55 @@ public class ConnectionInfoExchangeImpl extends ConnectionInfoExchange {
public Object getSynchronizationObject() {
return DataStorage.get();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
List<UUID> connections;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
List<@NonNull InfoResponse> infos;
}
@Jacksonized
@Builder
@Value
public static class InfoResponse {
@NonNull
UUID connection;
@NonNull
StorePath category;
@NonNull
StorePath name;
@NonNull
String type;
@NonNull
Object rawData;
@NonNull
Object usageCategory;
@NonNull
Instant lastUsed;
@NonNull
Instant lastModified;
@NonNull
Object state;
@NonNull
Map<String, Object> cache;
}
}
@@ -1,7 +1,10 @@
package io.xpipe.beacon.api;
package io.xpipe.app.beacon.api;
import io.xpipe.beacon.BeaconInterface;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStorageQuery;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
@@ -17,6 +20,20 @@ public class ConnectionQueryExchange extends BeaconInterface<ConnectionQueryExch
return "/connection/query";
}
@Override
public Object handle(HttpExchange exchange, Request msg) {
var found =
DataStorageQuery.queryEntry(msg.getCategoryFilter(), msg.getConnectionFilter(), msg.getTypeFilter());
return Response.builder()
.found(found.stream().map(entry -> entry.getUuid()).toList())
.build();
}
@Override
public Object getSynchronizationObject() {
return DataStorage.get();
}
@Jacksonized
@Builder
@Value
@@ -1,13 +1,24 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.ext.FixedHierarchyStore;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.ConnectionRefreshExchange;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import com.sun.net.httpserver.HttpExchange;
import java.util.UUID;
public class ConnectionRefreshExchangeImpl extends ConnectionRefreshExchange {
public class ConnectionRefreshExchange extends BeaconInterface<ConnectionRefreshExchange.Request> {
@Override
public String getPath() {
return "/connection/refresh";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws Throwable {
@@ -26,4 +37,17 @@ public class ConnectionRefreshExchangeImpl extends ConnectionRefreshExchange {
public Object getSynchronizationObject() {
return DataStorage.get();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID connection;
}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -1,16 +1,26 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.ConnectionRemoveExchange;
import com.sun.net.httpserver.HttpExchange;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ConnectionRemoveExchangeImpl extends ConnectionRemoveExchange {
public class ConnectionRemoveExchange extends BeaconInterface<ConnectionRemoveExchange.Request> {
@Override
public String getPath() {
return "/connection/remove";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException {
@@ -29,4 +39,17 @@ public class ConnectionRemoveExchangeImpl extends ConnectionRemoveExchange {
public Object getSynchronizationObject() {
return DataStorage.get();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
List<UUID> connections;
}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -1,12 +1,20 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.core.mode.AppOperationMode;
import io.xpipe.app.core.window.AppMainWindow;
import io.xpipe.beacon.api.DaemonFocusExchange;
import lombok.Builder;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import com.sun.net.httpserver.HttpExchange;
public class DaemonFocusExchange extends BeaconInterface<DaemonFocusExchange.Request> {
public class DaemonFocusExchangeImpl extends DaemonFocusExchange {
@Override
public String getPath() {
return "/daemon/focus";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws Throwable {
@@ -34,4 +42,14 @@ public class DaemonFocusExchangeImpl extends DaemonFocusExchange {
public boolean requiresCompletedStartup() {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -1,12 +1,23 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.core.mode.AppOperationMode;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.DaemonModeExchange;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.core.mode.AppOperationMode;
import io.xpipe.app.util.XPipeDaemonMode;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
public class DaemonModeExchange extends BeaconInterface<DaemonModeExchange.Request> {
@Override
public String getPath() {
return "/daemon/mode";
}
public class DaemonModeExchangeImpl extends DaemonModeExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException {
var mode = AppOperationMode.map(msg.getMode());
@@ -22,11 +33,27 @@ public class DaemonModeExchangeImpl extends DaemonModeExchange {
}
AppOperationMode.switchToSyncIfPossible(mode);
return DaemonModeExchange.Response.builder().usedMode(msg.getMode()).build();
return Response.builder().usedMode(msg.getMode()).build();
}
@Override
public boolean requiresEnabledApi() {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
XPipeDaemonMode mode;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
XPipeDaemonMode usedMode;
}
}
@@ -1,18 +1,29 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.beacon.BeaconServerException;
import io.xpipe.app.core.AppOpenArguments;
import io.xpipe.app.core.mode.AppOperationMode;
import io.xpipe.app.platform.PlatformInit;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.DaemonOpenExchange;
import io.xpipe.core.OsType;
import io.xpipe.app.util.OsType;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import com.sun.net.httpserver.HttpExchange;
import java.util.List;
public class DaemonOpenExchangeImpl extends DaemonOpenExchange {
public class DaemonOpenExchange extends BeaconInterface<DaemonOpenExchange.Request> {
private int openCounter = 0;
@Override
public String getPath() {
return "/daemon/open";
}
@Override
public boolean requiresCompletedStartup() {
return false;
@@ -46,4 +57,17 @@ public class DaemonOpenExchangeImpl extends DaemonOpenExchange {
public boolean requiresEnabledApi() {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
List<String> arguments;
}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -1,11 +1,19 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.core.mode.AppOperationMode;
import io.xpipe.beacon.api.DaemonStatusExchange;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
public class DaemonStatusExchangeImpl extends DaemonStatusExchange {
import io.xpipe.app.core.mode.AppOperationMode;
import lombok.Builder;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
public class DaemonStatusExchange extends BeaconInterface<DaemonStatusExchange.Request> {
@Override
public String getPath() {
return "/daemon/status";
}
@Override
public boolean requiresCompletedStartup() {
@@ -28,4 +36,16 @@ public class DaemonStatusExchangeImpl extends DaemonStatusExchange {
public boolean requiresEnabledApi() {
return false;
}
@Value
@Jacksonized
@Builder
public static class Request {}
@Jacksonized
@Builder
@Value
public static class Response {
String mode;
}
}
@@ -1,12 +1,23 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.core.mode.AppOperationMode;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.beacon.api.DaemonStopExchange;
import lombok.Builder;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import com.sun.net.httpserver.HttpExchange;
/**
* Requests the daemon to stop.
*/
public class DaemonStopExchange extends BeaconInterface<DaemonStopExchange.Request> {
public class DaemonStopExchangeImpl extends DaemonStopExchange {
@Override
public String getPath() {
return "/daemon/stop";
}
@Override
public boolean requiresCompletedStartup() {
@@ -26,4 +37,16 @@ public class DaemonStopExchangeImpl extends DaemonStopExchange {
public boolean requiresEnabledApi() {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {}
@Jacksonized
@Builder
@Value
public static class Response {
boolean success;
}
}
@@ -1,13 +1,22 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.core.AppVersion;
import io.xpipe.app.util.LicenseProvider;
import io.xpipe.beacon.api.DaemonVersionExchange;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import com.sun.net.httpserver.HttpExchange;
public class DaemonVersionExchange extends BeaconInterface<DaemonVersionExchange.Request> {
public class DaemonVersionExchangeImpl extends DaemonVersionExchange {
@Override
public String getPath() {
return "/daemon/version";
}
@Override
public boolean requiresCompletedStartup() {
@@ -34,4 +43,30 @@ public class DaemonVersionExchangeImpl extends DaemonVersionExchange {
public boolean requiresEnabledApi() {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
String version;
@NonNull
String canonicalVersion;
@NonNull
String buildVersion;
@NonNull
String jvmVersion;
@NonNull
String plan;
}
}
@@ -0,0 +1,53 @@
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.beacon.BlobManager;
import lombok.Builder;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.UUID;
public class FsBlobExchange extends BeaconInterface<FsBlobExchange.Request> {
@Override
public String getPath() {
return "/fs/blob";
}
@Override
public boolean readRawRequestBody() {
return true;
}
@Override
@SneakyThrows
public Object handle(HttpExchange exchange, Request msg) {
var id = UUID.randomUUID();
var size = exchange.getRequestBody().available();
if (size > 100_000_000) {
BlobManager.get().store(id, exchange.getRequestBody());
} else {
BlobManager.get().store(id, exchange.getRequestBody().readAllBytes());
}
return Response.builder().blob(id).build();
}
@Jacksonized
@Builder
@Value
public static class Request {}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
UUID blob;
}
}
@@ -1,20 +1,31 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BlobManager;
import io.xpipe.app.ext.ConnectionFileSystem;
import io.xpipe.app.util.FixedSizeInputStream;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.FsReadExchange;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.beacon.BlobManager;
import io.xpipe.app.ext.ConnectionFileSystem;
import io.xpipe.app.util.FilePath;
import io.xpipe.app.util.FixedSizeInputStream;
import lombok.Builder;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.io.BufferedInputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.UUID;
public class FsReadExchangeImpl extends FsReadExchange {
public class FsReadExchange extends BeaconInterface<FsReadExchange.Request> {
@Override
public String getPath() {
return "/fs/read";
}
@Override
@SneakyThrows
@@ -56,4 +67,20 @@ public class FsReadExchangeImpl extends FsReadExchange {
}
return Response.builder().build();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID connection;
@NonNull
FilePath path;
}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -1,16 +1,27 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BlobManager;
import io.xpipe.app.process.ScriptHelper;
import io.xpipe.beacon.api.FsScriptExchange;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.beacon.BlobManager;
import io.xpipe.app.process.ScriptHelper;
import io.xpipe.app.util.FilePath;
import lombok.Builder;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
public class FsScriptExchangeImpl extends FsScriptExchange {
public class FsScriptExchange extends BeaconInterface<FsScriptExchange.Request> {
@Override
public String getPath() {
return "/fs/script";
}
@Override
@SneakyThrows
@@ -24,4 +35,23 @@ public class FsScriptExchangeImpl extends FsScriptExchange {
var file = ScriptHelper.createExecScript(shell.getControl(), data);
return Response.builder().path(file).build();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID connection;
@NonNull
UUID blob;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
FilePath path;
}
}
@@ -0,0 +1,55 @@
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.beacon.BlobManager;
import io.xpipe.app.ext.ConnectionFileSystem;
import io.xpipe.app.util.FilePath;
import lombok.Builder;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.UUID;
public class FsWriteExchange extends BeaconInterface<FsWriteExchange.Request> {
@Override
public String getPath() {
return "/fs/write";
}
@Override
@SneakyThrows
public Object handle(HttpExchange exchange, Request msg) {
var shell = AppBeaconServer.get().getCache().getShellSession(msg.getConnection());
var fs = new ConnectionFileSystem(shell.getControl());
try (var in = BlobManager.get().getBlob(msg.getBlob());
var os = fs.openOutput(msg.getPath(), in.available())) {
in.transferTo(os);
}
return Response.builder().build();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID connection;
@NonNull
UUID blob;
@NonNull
FilePath path;
}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -1,18 +1,34 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BeaconSession;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.beacon.BeaconAuthMethod;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.HandshakeExchange;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.*;
import io.xpipe.app.beacon.BeaconAuthMethod;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.AppPrefs;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.UUID;
public class HandshakeExchangeImpl extends HandshakeExchange {
public class HandshakeExchange extends BeaconInterface<HandshakeExchange.Request> {
@Override
public boolean acceptInShutdown() {
return true;
}
@Override
public boolean requiresAuthentication() {
return false;
}
@Override
public String getPath() {
return "/handshake";
}
@Override
public boolean requiresCompletedStartup() {
@@ -39,7 +55,7 @@ public class HandshakeExchangeImpl extends HandshakeExchange {
return false;
}
private boolean checkAuth(BeaconAuthMethod authMethod) {
private boolean checkAuth(io.xpipe.app.beacon.BeaconAuthMethod authMethod) {
if (authMethod instanceof BeaconAuthMethod.Local local) {
var c = local.getAuthFileContent().strip();
return AppBeaconServer.get().getLocalAuthSecret().equals(c);
@@ -52,4 +68,23 @@ public class HandshakeExchangeImpl extends HandshakeExchange {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
BeaconAuthMethod auth;
@NonNull
BeaconClientInformation client;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
String sessionToken;
}
}
@@ -0,0 +1,48 @@
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import com.fasterxml.jackson.databind.JsonNode;
import io.xpipe.app.storage.DataStorageSecret;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.io.IOException;
public class SecretDecryptExchange extends BeaconInterface<SecretDecryptExchange.Request> {
@Override
public String getPath() {
return "/secret/decrypt";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws IOException, BeaconClientException {
var secret = DataStorageSecret.deserialize(msg.getEncrypted());
if (secret == null) {
throw new BeaconClientException("Unable to parse secret");
}
return Response.builder().decrypted(new String(secret.getSecret())).build();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
JsonNode encrypted;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
String decrypted;
}
}
@@ -1,8 +1,11 @@
package io.xpipe.beacon.api;
package io.xpipe.app.beacon.api;
import io.xpipe.beacon.BeaconInterface;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import com.fasterxml.jackson.databind.JsonNode;
import io.xpipe.app.storage.DataStorageSecret;
import io.xpipe.app.util.InPlaceSecretValue;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
@@ -15,6 +18,12 @@ public class SecretEncryptExchange extends BeaconInterface<SecretEncryptExchange
return "/secret/encrypt";
}
@Override
public Object handle(HttpExchange exchange, Request msg) {
var secret = DataStorageSecret.ofCurrentSecret(InPlaceSecretValue.of(msg.getValue()));
return Response.builder().encrypted(secret.serialize(true)).build();
}
@Jacksonized
@Builder
@Value
@@ -1,14 +1,24 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.beacon.api.ShellExecExchange;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import lombok.SneakyThrows;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BeaconInterface;
import lombok.Builder;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
public class ShellExecExchangeImpl extends ShellExecExchange {
public class ShellExecExchange extends BeaconInterface<ShellExecExchange.Request> {
@Override
public String getPath() {
return "/shell/exec";
}
@Override
@SneakyThrows
@@ -30,4 +40,28 @@ public class ShellExecExchangeImpl extends ShellExecExchange {
.exitCode(exitCode)
.build();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID connection;
@NonNull
String command;
}
@Jacksonized
@Builder
@Value
public static class Response {
long exitCode;
@NonNull
String stdout;
@NonNull
String stderr;
}
}
@@ -1,17 +1,30 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.beacon.BeaconShellSession;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.ShellStartExchange;
import io.xpipe.core.JacksonMapper;
import io.xpipe.app.util.FilePath;
import io.xpipe.app.util.JacksonMapper;
import io.xpipe.app.util.OsType;
import com.sun.net.httpserver.HttpExchange;
import lombok.Builder;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
public class ShellStartExchangeImpl extends ShellStartExchange {
import java.util.UUID;
public class ShellStartExchange extends BeaconInterface<ShellStartExchange.Request> {
@Override
public String getPath() {
return "/shell/start";
}
@Override
@SneakyThrows
@@ -51,4 +64,32 @@ public class ShellStartExchangeImpl extends ShellStartExchange {
.ttyState(ttyState)
.build();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID connection;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
String shellDialect;
@NonNull
OsType.Any osType;
@NonNull
String osName;
@NonNull
String ttyState;
@NonNull
FilePath temp;
}
}
@@ -0,0 +1,43 @@
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BeaconInterface;
import lombok.Builder;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.UUID;
public class ShellStopExchange extends BeaconInterface<ShellStopExchange.Request> {
@Override
public String getPath() {
return "/shell/stop";
}
@Override
@SneakyThrows
public Object handle(HttpExchange exchange, Request msg) {
var e = AppBeaconServer.get().getCache().getShellSession(msg.getConnection());
e.getControl().close();
AppBeaconServer.get().getCache().getShellSessions().remove(e);
return Response.builder().build();
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID connection;
}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -1,15 +1,24 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.ext.ProcessControlProvider;
import io.xpipe.app.process.ShellDialects;
import io.xpipe.app.terminal.TerminalLauncherManager;
import io.xpipe.beacon.api.SshLaunchExchange;
import com.sun.net.httpserver.HttpExchange;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.List;
public class SshLaunchExchangeImpl extends SshLaunchExchange {
public class SshLaunchExchange extends BeaconInterface<SshLaunchExchange.Request> {
@Override
public String getPath() {
return "/sshLaunch";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws Exception {
@@ -40,4 +49,19 @@ public class SshLaunchExchangeImpl extends SshLaunchExchange {
public boolean requiresEnabledApi() {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {
String arguments;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
List<String> command;
}
}
@@ -1,5 +1,10 @@
package io.xpipe.app.beacon.impl;
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.beacon.BeaconServerException;
import io.xpipe.app.core.AppCache;
import io.xpipe.app.core.window.AppDialog;
import io.xpipe.app.ext.ShellStore;
@@ -7,15 +12,19 @@ import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStorageQuery;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.terminal.TerminalLauncherManager;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.TerminalExternalLaunchExchange;
import com.sun.net.httpserver.HttpExchange;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.List;
public class TerminalExternalLaunchExchangeImpl extends TerminalExternalLaunchExchange {
public class TerminalExternalLaunchExchange extends BeaconInterface<TerminalExternalLaunchExchange.Request> {
@Override
public String getPath() {
return "/terminal/externalLaunch";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException, BeaconServerException {
@@ -66,4 +75,23 @@ public class TerminalExternalLaunchExchangeImpl extends TerminalExternalLaunchEx
}
return r;
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
String connection;
@NonNull
List<String> arguments;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
List<String> command;
}
}
@@ -0,0 +1,50 @@
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.beacon.BeaconServerException;
import io.xpipe.app.terminal.TerminalLauncherManager;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.nio.file.Path;
import java.util.UUID;
public class TerminalLaunchExchange extends BeaconInterface<TerminalLaunchExchange.Request> {
@Override
public String getPath() {
return "/terminal/launch";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException, BeaconServerException {
var r = TerminalLauncherManager.launchExchange(msg.getRequest());
return Response.builder().targetFile(r).build();
}
@Override
public boolean requiresEnabledApi() {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID request;
}
@Jacksonized
@Builder
@Value
public static class Response {
@NonNull
Path targetFile;
}
}
@@ -0,0 +1,54 @@
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.prefs.AppPrefs;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.UUID;
public class TerminalPrepareExchange extends BeaconInterface<TerminalPrepareExchange.Request> {
@Override
public String getPath() {
return "/terminal/prepare";
}
@Override
public Object handle(HttpExchange exchange, Request msg) {
var term = AppPrefs.get().terminalType().getValue();
var unicode = term.supportsUnicode();
var escapes = term.supportsEscapes();
return Response.builder()
.supportsUnicode(unicode)
.supportsEscapeSequences(escapes)
.build();
}
@Override
public boolean requiresEnabledApi() {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID request;
long pid;
}
@Jacksonized
@Builder
@Value
public static class Response {
boolean supportsUnicode;
boolean supportsEscapeSequences;
}
}
@@ -0,0 +1,49 @@
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.terminal.TerminalLauncherManager;
import io.xpipe.app.terminal.TerminalView;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.UUID;
public class TerminalRegisterExchange extends BeaconInterface<TerminalRegisterExchange.Request> {
@Override
public String getPath() {
return "/terminal/register";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException {
TerminalView.get().open(msg.getRequest(), msg.getPid());
TerminalLauncherManager.registerPid(msg.getRequest(), msg.getPid());
return Response.builder().build();
}
@Override
public boolean requiresEnabledApi() {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID request;
long pid;
}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -0,0 +1,45 @@
package io.xpipe.app.beacon.api;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.beacon.BeaconServerException;
import io.xpipe.app.terminal.TerminalLauncherManager;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
import java.util.UUID;
public class TerminalWaitExchange extends BeaconInterface<TerminalWaitExchange.Request> {
@Override
public String getPath() {
return "/terminal/wait";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconServerException {
TerminalLauncherManager.waitExchange(msg.getRequest());
return Response.builder().build();
}
@Override
public boolean requiresEnabledApi() {
return false;
}
@Jacksonized
@Builder
@Value
public static class Request {
@NonNull
UUID request;
}
@Jacksonized
@Builder
@Value
public static class Response {}
}
@@ -1,23 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStorageQuery;
import io.xpipe.beacon.api.CategoryQueryExchange;
import com.sun.net.httpserver.HttpExchange;
public class CategoryQueryExchangeImpl extends CategoryQueryExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) {
var found = DataStorageQuery.queryCategory(msg.getFilter());
return Response.builder()
.found(found.stream().map(entry -> entry.getUuid()).toList())
.build();
}
@Override
public Object getSynchronizationObject() {
return DataStorage.get();
}
}
@@ -1,24 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStorageQuery;
import io.xpipe.beacon.api.ConnectionQueryExchange;
import com.sun.net.httpserver.HttpExchange;
public class ConnectionQueryExchangeImpl extends ConnectionQueryExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) {
var found =
DataStorageQuery.queryEntry(msg.getCategoryFilter(), msg.getConnectionFilter(), msg.getTypeFilter());
return Response.builder()
.found(found.stream().map(entry -> entry.getUuid()).toList())
.build();
}
@Override
public Object getSynchronizationObject() {
return DataStorage.get();
}
}
@@ -1,26 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.beacon.BlobManager;
import io.xpipe.beacon.api.FsBlobExchange;
import com.sun.net.httpserver.HttpExchange;
import lombok.SneakyThrows;
import java.util.UUID;
public class FsBlobExchangeImpl extends FsBlobExchange {
@Override
@SneakyThrows
public Object handle(HttpExchange exchange, Request msg) {
var id = UUID.randomUUID();
var size = exchange.getRequestBody().available();
if (size > 100_000_000) {
BlobManager.get().store(id, exchange.getRequestBody());
} else {
BlobManager.get().store(id, exchange.getRequestBody().readAllBytes());
}
return Response.builder().blob(id).build();
}
}
@@ -1,24 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BlobManager;
import io.xpipe.app.ext.ConnectionFileSystem;
import io.xpipe.beacon.api.FsWriteExchange;
import com.sun.net.httpserver.HttpExchange;
import lombok.SneakyThrows;
public class FsWriteExchangeImpl extends FsWriteExchange {
@Override
@SneakyThrows
public Object handle(HttpExchange exchange, Request msg) {
var shell = AppBeaconServer.get().getCache().getShellSession(msg.getConnection());
var fs = new ConnectionFileSystem(shell.getControl());
try (var in = BlobManager.get().getBlob(msg.getBlob());
var os = fs.openOutput(msg.getPath(), in.available())) {
in.transferTo(os);
}
return Response.builder().build();
}
}
@@ -1,22 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.storage.DataStorageSecret;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.SecretDecryptExchange;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
public class SecretDecryptExchangeImpl extends SecretDecryptExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) throws IOException, BeaconClientException {
var secret = DataStorageSecret.deserialize(msg.getEncrypted());
if (secret == null) {
throw new BeaconClientException("Unable to parse secret");
}
return Response.builder().decrypted(new String(secret.getSecret())).build();
}
}
@@ -1,16 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.storage.DataStorageSecret;
import io.xpipe.beacon.api.SecretEncryptExchange;
import io.xpipe.core.InPlaceSecretValue;
import com.sun.net.httpserver.HttpExchange;
public class SecretEncryptExchangeImpl extends SecretEncryptExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) {
var secret = DataStorageSecret.ofCurrentSecret(InPlaceSecretValue.of(msg.getValue()));
return Response.builder().encrypted(secret.serialize(true)).build();
}
}
@@ -1,19 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.beacon.api.ShellStopExchange;
import com.sun.net.httpserver.HttpExchange;
import lombok.SneakyThrows;
public class ShellStopExchangeImpl extends ShellStopExchange {
@Override
@SneakyThrows
public Object handle(HttpExchange exchange, Request msg) {
var e = AppBeaconServer.get().getCache().getShellSession(msg.getConnection());
e.getControl().close();
AppBeaconServer.get().getCache().getShellSessions().remove(e);
return Response.builder().build();
}
}
@@ -1,21 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.terminal.TerminalLauncherManager;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.TerminalLaunchExchange;
import com.sun.net.httpserver.HttpExchange;
public class TerminalLaunchExchangeImpl extends TerminalLaunchExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException, BeaconServerException {
var r = TerminalLauncherManager.launchExchange(msg.getRequest());
return Response.builder().targetFile(r).build();
}
@Override
public boolean requiresEnabledApi() {
return false;
}
}
@@ -1,25 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.beacon.api.TerminalPrepareExchange;
import com.sun.net.httpserver.HttpExchange;
public class TerminalPrepareExchangeImpl extends TerminalPrepareExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) {
var term = AppPrefs.get().terminalType().getValue();
var unicode = term.supportsUnicode();
var escapes = term.supportsEscapes();
return Response.builder()
.supportsUnicode(unicode)
.supportsEscapeSequences(escapes)
.build();
}
@Override
public boolean requiresEnabledApi() {
return false;
}
}
@@ -1,23 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.terminal.TerminalLauncherManager;
import io.xpipe.app.terminal.TerminalView;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.TerminalRegisterExchange;
import com.sun.net.httpserver.HttpExchange;
public class TerminalRegisterExchangeImpl extends TerminalRegisterExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException {
TerminalView.get().open(msg.getRequest(), msg.getPid());
TerminalLauncherManager.registerPid(msg.getRequest(), msg.getPid());
return Response.builder().build();
}
@Override
public boolean requiresEnabledApi() {
return false;
}
}
@@ -1,21 +0,0 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.terminal.TerminalLauncherManager;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.TerminalWaitExchange;
import com.sun.net.httpserver.HttpExchange;
public class TerminalWaitExchangeImpl extends TerminalWaitExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconServerException {
TerminalLauncherManager.waitExchange(msg.getRequest());
return Response.builder().build();
}
@Override
public boolean requiresEnabledApi() {
return false;
}
}
@@ -1,6 +1,6 @@
package io.xpipe.app.beacon.mcp;
import io.xpipe.core.JacksonMapper;
import io.xpipe.app.util.JacksonMapper;
import io.modelcontextprotocol.spec.McpSchema;
@@ -6,8 +6,8 @@ import io.xpipe.app.process.ShellControl;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStorageQuery;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.core.FilePath;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.util.FilePath;
import io.modelcontextprotocol.server.McpSyncServerExchange;
import io.modelcontextprotocol.spec.McpSchema;
@@ -13,10 +13,10 @@ import io.xpipe.app.storage.DataStorageQuery;
import io.xpipe.app.terminal.TerminalLaunch;
import io.xpipe.app.util.CommandDialog;
import io.xpipe.app.util.HttpHelper;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.BeaconInterface;
import io.xpipe.core.FilePath;
import io.xpipe.core.JacksonMapper;
import io.xpipe.app.beacon.BeaconClientException;
import io.xpipe.app.beacon.BeaconInterface;
import io.xpipe.app.util.FilePath;
import io.xpipe.app.util.JacksonMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import io.modelcontextprotocol.json.jackson2.JacksonMcpJsonMapper;
@@ -21,7 +21,7 @@ import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.FileReference;
import io.xpipe.app.util.ObservableSubscriber;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
@@ -8,8 +8,8 @@ import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.FileReference;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.FailableFunction;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FailableFunction;
import io.xpipe.app.util.FilePath;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
@@ -13,8 +13,8 @@ import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.FailableFunction;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FailableFunction;
import io.xpipe.app.util.FilePath;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
@@ -8,7 +8,7 @@ import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.ext.FileSystemStore;
import io.xpipe.app.hub.action.StoreAction;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
@@ -2,7 +2,7 @@ package io.xpipe.app.browser.action.impl;
import io.xpipe.app.browser.action.BrowserAction;
import io.xpipe.app.browser.action.BrowserActionProvider;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import lombok.NonNull;
import lombok.experimental.SuperBuilder;
@@ -4,7 +4,7 @@ import io.xpipe.app.browser.action.BrowserAction;
import io.xpipe.app.browser.action.BrowserActionProvider;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.ext.FileKind;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import lombok.NonNull;
import lombok.experimental.SuperBuilder;
@@ -8,7 +8,7 @@ import io.xpipe.app.ext.FileKind;
import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.LocalShell;
import io.xpipe.app.process.ShellControl;
import io.xpipe.core.OsType;
import io.xpipe.app.util.OsType;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;
@@ -6,7 +6,7 @@ import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.file.BrowserFileOpener;
import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.ext.FileKind;
import io.xpipe.core.OsType;
import io.xpipe.app.util.OsType;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;
@@ -5,7 +5,7 @@ import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.GlobalTimer;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.application.Platform;
import javafx.css.PseudoClass;
@@ -4,7 +4,7 @@ import io.xpipe.app.comp.base.ModalButton;
import io.xpipe.app.comp.base.ModalOverlay;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.window.AppDialog;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.beans.property.SimpleObjectProperty;
@@ -1,7 +1,7 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.ext.FileSystem;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import java.util.regex.Pattern;
@@ -6,8 +6,8 @@ import io.xpipe.app.ext.FileEntry;
import io.xpipe.app.ext.FileInfo;
import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.ElevationFunction;
import io.xpipe.core.FilePath;
import io.xpipe.core.OsType;
import io.xpipe.app.util.FilePath;
import io.xpipe.app.util.OsType;
import java.io.InputStream;
@@ -7,7 +7,7 @@ import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.GlobalTimer;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.OsType;
import io.xpipe.app.util.OsType;
import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
@@ -5,7 +5,7 @@ import io.xpipe.app.ext.FileEntry;
import io.xpipe.app.ext.FileKind;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
@@ -9,7 +9,7 @@ import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
@@ -9,8 +9,8 @@ import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.ElevationFunction;
import io.xpipe.app.process.ProcessOutputException;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.core.FilePath;
import io.xpipe.core.OsType;
import io.xpipe.app.util.FilePath;
import io.xpipe.app.util.OsType;
import java.io.OutputStream;
import java.util.List;
@@ -4,8 +4,8 @@ import io.xpipe.app.ext.FileEntry;
import io.xpipe.app.ext.FileKind;
import io.xpipe.app.ext.FileSystem;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.core.FilePath;
import io.xpipe.core.OsType;
import io.xpipe.app.util.FilePath;
import io.xpipe.app.util.OsType;
import java.time.Instant;
import java.util.List;
@@ -1,6 +1,6 @@
package io.xpipe.app.browser.file;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
@@ -2,8 +2,8 @@ package io.xpipe.app.browser.file;
import io.xpipe.app.core.AppCache;
import io.xpipe.app.util.GlobalTimer;
import io.xpipe.core.FilePath;
import io.xpipe.core.JacksonMapper;
import io.xpipe.app.util.FilePath;
import io.xpipe.app.util.JacksonMapper;
import javafx.application.Platform;
import javafx.collections.FXCollections;
@@ -10,7 +10,7 @@ import io.xpipe.app.platform.InputHelper;
import io.xpipe.app.platform.MenuHelper;
import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.util.GlobalTimer;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyBooleanWrapper;
@@ -18,9 +18,9 @@ import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.terminal.*;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.FailableFunction;
import io.xpipe.core.FilePath;
import io.xpipe.core.OsType;
import io.xpipe.app.util.FailableFunction;
import io.xpipe.app.util.FilePath;
import io.xpipe.app.util.OsType;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
@@ -6,7 +6,7 @@ import io.xpipe.app.ext.FileKind;
import io.xpipe.app.ext.FileSystem;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.beans.property.BooleanProperty;
import javafx.beans.value.ChangeListener;
@@ -1,6 +1,6 @@
package io.xpipe.app.browser.file;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.collections.ObservableList;
@@ -1,7 +1,7 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.core.AppCache;
import io.xpipe.core.JacksonMapper;
import io.xpipe.app.util.JacksonMapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@@ -4,7 +4,7 @@ import io.xpipe.app.ext.FileEntry;
import io.xpipe.app.ext.FileKind;
import io.xpipe.app.ext.FileSystem;
import io.xpipe.app.ext.LocalStore;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -9,7 +9,7 @@ import io.xpipe.app.ext.FileEntry;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.platform.DerivedObservableList;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
@@ -8,7 +8,7 @@ import io.xpipe.app.browser.menu.BrowserMenuCategory;
import io.xpipe.app.browser.menu.BrowserMenuLeafProvider;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.core.OsType;
import io.xpipe.app.util.OsType;
import javafx.beans.value.ObservableValue;
@@ -10,7 +10,7 @@ import io.xpipe.app.ext.FileKind;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.OsType;
import io.xpipe.app.util.OsType;
import javafx.beans.value.ObservableValue;
import javafx.scene.input.KeyCode;
@@ -10,7 +10,7 @@ import io.xpipe.app.core.AppI18n;
import io.xpipe.app.ext.FileKind;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.app.process.CommandBuilder;
import io.xpipe.core.OsType;
import io.xpipe.app.util.OsType;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
@@ -15,7 +15,7 @@ import io.xpipe.app.core.AppI18n;
import io.xpipe.app.ext.FileKind;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.app.platform.OptionsBuilder;
import io.xpipe.core.FilePath;
import io.xpipe.app.util.FilePath;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
@@ -8,7 +8,7 @@ import io.xpipe.app.browser.menu.BrowserMenuCategory;
import io.xpipe.app.browser.menu.BrowserMenuLeafProvider;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.core.OsType;
import io.xpipe.app.util.OsType;
import javafx.beans.value.ObservableValue;
import javafx.scene.input.KeyCode;
@@ -9,7 +9,7 @@ import io.xpipe.app.browser.menu.BrowserMenuLeafProvider;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.ext.FileKind;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.core.OsType;
import io.xpipe.app.util.OsType;
import javafx.beans.value.ObservableValue;

Some files were not shown because too many files have changed in this diff Show More