mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-05-29 07:20:35 +00:00
Rework
This commit is contained in:
@@ -123,6 +123,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())
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ 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;
|
||||
|
||||
@@ -56,7 +56,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).orElse(AppProperties.get().getDefaultBeaconPort()));
|
||||
INSTANCE.initAuthSecret();
|
||||
INSTANCE.start();
|
||||
TrackEvent.withInfo("Started http server")
|
||||
@@ -111,7 +112,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 +123,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();
|
||||
|
||||
@@ -185,13 +185,13 @@ public abstract class AppInstallation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getLangPath() {
|
||||
return getBaseInstallationPath().resolve("lang");
|
||||
public Path getCliExecutablePath() {
|
||||
return getBaseInstallationPath().resolve("xpipe.exe");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getCliExecutablePath() {
|
||||
return getBaseInstallationPath().resolve("bin", "xpipe.exe");
|
||||
public Path getLangPath() {
|
||||
return getBaseInstallationPath().resolve("lang");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -243,13 +243,13 @@ public abstract class AppInstallation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getLangPath() {
|
||||
return getBaseInstallationPath().resolve("lang");
|
||||
public Path getCliExecutablePath() {
|
||||
return getBaseInstallationPath().resolve("bin", "xpipe");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getCliExecutablePath() {
|
||||
return getBaseInstallationPath().resolve("bin", "xpipe");
|
||||
public Path getLangPath() {
|
||||
return getBaseInstallationPath().resolve("lang");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -303,6 +303,11 @@ public abstract class AppInstallation {
|
||||
AppNames.ofCurrent().getExecutableName() + "_debug.sh");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getCliExecutablePath() {
|
||||
return getBaseInstallationPath().resolve("Contents", "MacOS", "xpipe");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getLangPath() {
|
||||
if (!AppProperties.get().isImage()) {
|
||||
@@ -312,11 +317,6 @@ public abstract class AppInstallation {
|
||||
return getBaseInstallationPath().resolve("Contents", "Resources", "lang");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getCliExecutablePath() {
|
||||
return getBaseInstallationPath().resolve("Contents", "MacOS", "xpipe");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getDaemonExecutablePath() {
|
||||
return getBaseInstallationPath()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.xpipe.app.core;
|
||||
|
||||
import io.xpipe.app.beacon.AppBeaconServer;
|
||||
import io.xpipe.app.core.mode.AppOperationMode;
|
||||
import io.xpipe.app.issue.ErrorEventFactory;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
@@ -8,16 +7,12 @@ import io.xpipe.app.util.DocumentationLink;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.beacon.BeaconClient;
|
||||
import io.xpipe.beacon.BeaconClientInformation;
|
||||
import io.xpipe.beacon.BeaconConfig;
|
||||
import io.xpipe.beacon.BeaconServer;
|
||||
import io.xpipe.beacon.api.DaemonFocusExchange;
|
||||
import io.xpipe.beacon.api.DaemonOpenExchange;
|
||||
import io.xpipe.core.OsType;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -30,7 +25,7 @@ public class AppInstance {
|
||||
public static Optional<BeaconClient> tryEstablishConnection(int port) {
|
||||
try {
|
||||
return Optional.of(BeaconClient.establishConnection(
|
||||
port, BeaconClientInformation.Daemon.builder().build()));
|
||||
port, BeaconClientInformation.Daemon.builder().build(), AppProperties.get().getBeaconAuthFile()));
|
||||
} catch (Exception ex) {
|
||||
ErrorEventFactory.fromThrowable(ex).omit().expected().handle();
|
||||
return Optional.empty();
|
||||
@@ -38,40 +33,17 @@ public class AppInstance {
|
||||
}
|
||||
|
||||
private static void checkStart(int attemptCounter) {
|
||||
var port = BeaconConfig.getUsedPort();
|
||||
var port = AppProperties.get().getDefaultBeaconPort();
|
||||
var reachable = BeaconServer.isReachable(port);
|
||||
|
||||
if (reachable) {
|
||||
// If an instance is running as another user, we cannot connect to it as the xpipe_auth file is inaccessible
|
||||
var authFile = BeaconConfig.getLocalBeaconAuthFile();
|
||||
var hasAuthFile = Files.exists(authFile);
|
||||
|
||||
// Make sure that it is not a leftover
|
||||
if (hasAuthFile) {
|
||||
try (var channel = new RandomAccessFile(BeaconConfig.getLocalBeaconLockFile().toFile(), "rw").getChannel()) {
|
||||
var lock = channel.tryLock();
|
||||
if (lock != null) {
|
||||
lock.release();
|
||||
Files.delete(authFile);
|
||||
hasAuthFile = false;
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
if (!hasAuthFile) {
|
||||
var replacement = BeaconConfig.fallBackToAnotherPort();
|
||||
if (replacement.isEmpty()) {
|
||||
ErrorEventFactory.fromMessage("Unable to find free beacon port")
|
||||
.term()
|
||||
.documentationLink(DocumentationLink.BEACON_PORT_BIND)
|
||||
.expected()
|
||||
.handle();
|
||||
AppOperationMode.halt(1);
|
||||
} else {
|
||||
port = replacement.getAsInt();
|
||||
reachable = false;
|
||||
}
|
||||
}
|
||||
var effectiveBeaconPort = AppProperties.get().queryEffectiveBeaconPort(reachable);
|
||||
if (effectiveBeaconPort.isEmpty()) {
|
||||
ErrorEventFactory.fromMessage("Unable to find free beacon port")
|
||||
.term()
|
||||
.documentationLink(DocumentationLink.BEACON_PORT_BIND)
|
||||
.expected()
|
||||
.handle();
|
||||
AppOperationMode.halt(1);
|
||||
}
|
||||
|
||||
if (!reachable) {
|
||||
|
||||
@@ -3,11 +3,17 @@ package io.xpipe.app.core;
|
||||
import io.xpipe.app.core.check.AppDirectoryPermissionsCheck;
|
||||
import io.xpipe.app.issue.ErrorEventFactory;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.beacon.BeaconServer;
|
||||
import io.xpipe.core.OsType;
|
||||
import io.xpipe.core.XPipeDaemonMode;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Value;
|
||||
import lombok.experimental.NonFinal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
@@ -56,6 +62,15 @@ public class AppProperties {
|
||||
boolean logPlatformDebug;
|
||||
String logLevel;
|
||||
String loginTarget;
|
||||
int defaultBeaconPort;
|
||||
Path beaconAuthFile;
|
||||
Path beaconLockFile;
|
||||
boolean debugCli;
|
||||
boolean isDaemon;
|
||||
boolean isCli;
|
||||
@NonFinal
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
Integer effectiveBeaconPort;
|
||||
|
||||
public AppProperties(String[] args) {
|
||||
var appDir = Path.of(System.getProperty("user.dir")).resolve("app");
|
||||
@@ -158,6 +173,12 @@ public class AppProperties {
|
||||
.orElse("info");
|
||||
loginTarget = Optional.ofNullable(System.getProperty(AppNames.propertyName("login")))
|
||||
.orElse(null);
|
||||
isCli = Optional.ofNullable(System.getProperty(AppNames.propertyName("isCli")))
|
||||
.map(Boolean::parseBoolean)
|
||||
.orElse(false);
|
||||
isDaemon = Optional.ofNullable(System.getProperty(AppNames.propertyName("isDaemon")))
|
||||
.map(Boolean::parseBoolean)
|
||||
.orElse(!isCli);
|
||||
|
||||
// We require the user dir from here
|
||||
AppDirectoryPermissionsCheck.checkDirectory(dataDir);
|
||||
@@ -180,6 +201,93 @@ public class AppProperties {
|
||||
.orElse(false);
|
||||
explicitMode = XPipeDaemonMode.getIfPresent(System.getProperty(AppNames.propertyName("mode")))
|
||||
.orElse(null);
|
||||
defaultBeaconPort = getDefaultBeaconPort(staging);
|
||||
beaconAuthFile = getLocalBeaconAuthFile(staging);
|
||||
beaconLockFile = beaconAuthFile.getParent().resolve("lock");
|
||||
clearLeftoverAuthFile();
|
||||
debugCli = Optional.ofNullable(System.getProperty(AppNames.propertyName("debugCli")))
|
||||
.map(Boolean::parseBoolean)
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
public OptionalInt queryEffectiveBeaconPort(boolean reachable) {
|
||||
if (!reachable) {
|
||||
effectiveBeaconPort = getDefaultBeaconPort();
|
||||
return OptionalInt.of(effectiveBeaconPort);
|
||||
}
|
||||
|
||||
var authFile = getBeaconAuthFile();
|
||||
if (!Files.exists(authFile)) {
|
||||
effectiveBeaconPort = getDefaultBeaconPort();
|
||||
return OptionalInt.of(effectiveBeaconPort);
|
||||
}
|
||||
|
||||
if (effectiveBeaconPort != null) {
|
||||
return OptionalInt.of(effectiveBeaconPort);
|
||||
}
|
||||
|
||||
var hasEnv = System.getenv("BEACON_PORT") != null || System.getenv("XPIPE_BEACON_PORT") != null;
|
||||
if (hasEnv) {
|
||||
return OptionalInt.empty();
|
||||
}
|
||||
|
||||
var start = 21723;
|
||||
for (int i = 0; i < 20; i++) {
|
||||
var p = start + i;
|
||||
var occupied = BeaconServer.isReachable(p);
|
||||
if (!occupied) {
|
||||
effectiveBeaconPort = p;
|
||||
return OptionalInt.of(p);
|
||||
}
|
||||
}
|
||||
return OptionalInt.empty();
|
||||
}
|
||||
|
||||
private void clearLeftoverAuthFile() {
|
||||
var hasAuthFile = Files.exists(beaconAuthFile);
|
||||
if (hasAuthFile) {
|
||||
try (var channel = new RandomAccessFile(beaconLockFile.toFile(), "rw").getChannel()) {
|
||||
var lock = channel.tryLock();
|
||||
if (lock != null) {
|
||||
lock.release();
|
||||
Files.delete(beaconAuthFile);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int getDefaultBeaconPort(boolean staging) {
|
||||
var customPortVar = System.getenv("XPIPE_BEACON_PORT");
|
||||
Integer customPort = null;
|
||||
if (customPortVar != null) {
|
||||
try {
|
||||
customPort = Integer.parseInt(customPortVar);
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
var rawPortProp = System.getProperty(AppNames.propertyName("beaconPort"));
|
||||
if (customPort == null && rawPortProp != null) {
|
||||
try {
|
||||
var parsed = Integer.parseInt(rawPortProp);
|
||||
customPort = parsed;
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
var effectivePort = customPort != null ? customPort : 21721 + (staging ? 1 : 0);;
|
||||
return effectivePort;
|
||||
}
|
||||
|
||||
private static Path getLocalBeaconAuthFile(boolean staging) {
|
||||
if (OsType.ofLocal() == OsType.LINUX) {
|
||||
var name = AppSystemInfo.ofCurrent().getUser();
|
||||
return AppSystemInfo.ofCurrent().getTemp().resolve(staging ? "xpipe-ptb" : "xpipe", name, "beacon-auth");
|
||||
} else {
|
||||
var path = AppSystemInfo.ofCurrent().getTemp().resolve(staging ? "xpipe-ptb" : "xpipe", "beacon-auth");
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isJUnitTest() {
|
||||
|
||||
@@ -4,6 +4,10 @@ import io.xpipe.app.beacon.AppBeaconServer;
|
||||
import io.xpipe.app.core.*;
|
||||
import io.xpipe.app.core.check.AppDebugModeCheck;
|
||||
import io.xpipe.app.core.window.AppMainWindow;
|
||||
import io.xpipe.app.core.window.AppSideWindow;
|
||||
import io.xpipe.app.core.window.AppWindowStyle;
|
||||
import io.xpipe.app.ext.CliProvider;
|
||||
import io.xpipe.app.ext.ExtensionException;
|
||||
import io.xpipe.app.issue.*;
|
||||
import io.xpipe.app.platform.PlatformInit;
|
||||
import io.xpipe.app.platform.PlatformState;
|
||||
@@ -109,10 +113,24 @@ public abstract class AppOperationMode {
|
||||
ErrorEventFactory.fromThrowable(ex).unhandled(true).build().handle();
|
||||
});
|
||||
|
||||
AppProperties.init(args);
|
||||
if (AppProperties.get().isCli()) {
|
||||
CliProvider.init(ModuleLayer.boot());
|
||||
var cli = CliProvider.get();
|
||||
if (cli == null) {
|
||||
throw ExtensionException.corrupt("Missing cli module");
|
||||
}
|
||||
var r = cli.execute(args);
|
||||
if (AppProperties.get().isAotTrainMode()) {
|
||||
r = 0;
|
||||
}
|
||||
halt(r);
|
||||
return;
|
||||
}
|
||||
|
||||
TrackEvent.info("Initial setup");
|
||||
AppMainWindow.loadingText("initializingApp");
|
||||
GlobalTimer.init();
|
||||
AppProperties.init(args);
|
||||
PlatformThreadWatcher.init();
|
||||
AppLogs.init();
|
||||
AppDebugModeCheck.printIfNeeded();
|
||||
@@ -273,7 +291,6 @@ public abstract class AppOperationMode {
|
||||
|
||||
public static void halt(int code) {
|
||||
synchronized (HALT_LOCK) {
|
||||
TrackEvent.info("Halting now!");
|
||||
AppLogs.teardown();
|
||||
Runtime.getRuntime().halt(code);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.xpipe.app.ext;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
public abstract class CliProvider {
|
||||
|
||||
private static CliProvider INSTANCE;
|
||||
|
||||
public static void init(ModuleLayer layer) {
|
||||
INSTANCE = ServiceLoader.load(layer, CliProvider.class).stream()
|
||||
.map(p -> p.get())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public static CliProvider get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public abstract int execute(String[] args);
|
||||
}
|
||||
@@ -128,6 +128,7 @@ open module io.xpipe.app {
|
||||
uses ProcessControlProvider;
|
||||
uses ShellDialect;
|
||||
uses CloudSetupProvider;
|
||||
uses CliProvider;
|
||||
|
||||
provides ActionProvider with
|
||||
GradleRunMenuProvider,
|
||||
|
||||
@@ -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,100 +0,0 @@
|
||||
package io.xpipe.beacon;
|
||||
|
||||
import io.xpipe.core.OsType;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
@UtilityClass
|
||||
public class BeaconConfig {
|
||||
|
||||
public static final String BEACON_PORT_PROP = "io.xpipe.beacon.port";
|
||||
private static final String PRINT_MESSAGES_PROPERTY = "io.xpipe.beacon.printMessages";
|
||||
private static Integer portOverride;
|
||||
|
||||
public static boolean printMessages() {
|
||||
if (System.getProperty(PRINT_MESSAGES_PROPERTY) != null) {
|
||||
return Boolean.parseBoolean(System.getProperty(PRINT_MESSAGES_PROPERTY));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int getUsedPort() {
|
||||
if (portOverride != null) {
|
||||
return portOverride;
|
||||
}
|
||||
|
||||
var beaconPort = System.getenv("BEACON_PORT");
|
||||
if (beaconPort != null && !beaconPort.isBlank()) {
|
||||
return Integer.parseInt(beaconPort);
|
||||
}
|
||||
|
||||
if (System.getProperty(BEACON_PORT_PROP) != null) {
|
||||
return Integer.parseInt(System.getProperty(BEACON_PORT_PROP));
|
||||
}
|
||||
|
||||
return getDefaultBeaconPort();
|
||||
}
|
||||
|
||||
public static OptionalInt fallBackToAnotherPort() {
|
||||
var hasEnv = System.getenv("BEACON_PORT") != null || System.getenv("XPIPE_BEACON_PORT") != null;
|
||||
if (hasEnv) {
|
||||
return OptionalInt.empty();
|
||||
}
|
||||
|
||||
var start = 21723;
|
||||
for (int i = 0; i < 20; i++) {
|
||||
var p = start + i;
|
||||
var occupied = BeaconServer.isReachable(p);
|
||||
if (!occupied) {
|
||||
portOverride = p;
|
||||
return OptionalInt.of(p);
|
||||
}
|
||||
}
|
||||
return OptionalInt.empty();
|
||||
}
|
||||
|
||||
public static int getDefaultBeaconPort() {
|
||||
var customPortVar = System.getenv("XPIPE_BEACON_PORT");
|
||||
Integer customPort = null;
|
||||
if (customPortVar != null) {
|
||||
try {
|
||||
customPort = Integer.parseInt(customPortVar);
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
var effectivePortBase = customPort != null ? customPort : 21721;
|
||||
|
||||
var staging = Optional.ofNullable(System.getProperty("io.xpipe.app.staging"))
|
||||
.map(Boolean::parseBoolean)
|
||||
.orElse(false);
|
||||
var offset = staging ? 1 : 0;
|
||||
|
||||
return effectivePortBase + offset;
|
||||
}
|
||||
|
||||
public static Path getLocalBeaconAuthFile() {
|
||||
var staging = Optional.ofNullable(System.getProperty("io.xpipe.app.staging"))
|
||||
.map(Boolean::parseBoolean)
|
||||
.orElse(false);
|
||||
if (OsType.ofLocal() == OsType.LINUX) {
|
||||
var name = System.getenv("USER") != null ? System.getenv("USER") : System.getProperty("user.name");
|
||||
return Path.of(System.getProperty("java.io.tmpdir"), staging ? "xpipe-ptb" : "xpipe", name, "beacon-auth");
|
||||
} else {
|
||||
var path = Path.of(System.getProperty("java.io.tmpdir"), staging ? "xpipe-ptb" : "xpipe", "beacon-auth");
|
||||
if (path.startsWith(Path.of("C:\\Windows"))) {
|
||||
path = Path.of(System.getenv("LOCALAPPDATA"))
|
||||
.resolve("Temp", staging ? "xpipe-ptb" : "xpipe", "beacon-auth");
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
public static Path getLocalBeaconLockFile() {
|
||||
return getLocalBeaconAuthFile().getParent().resolve("lock");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -224,7 +224,7 @@ project.ext {
|
||||
ci = System.getenv('CI') != null
|
||||
obfuscate = true
|
||||
fullVersion = file("$rootDir/private_files.txt").exists()
|
||||
bundleCds = ci && fullVersion
|
||||
bundleCds = true
|
||||
|
||||
// Names
|
||||
productName = isStage ? 'XPipe PTB' : 'XPipe'
|
||||
|
||||
Vendored
-1
@@ -96,7 +96,6 @@ apply from: 'jpackage.gradle'
|
||||
if (fullVersion) {
|
||||
apply from: 'train.gradle'
|
||||
apply from: 'base_full.gradle'
|
||||
apply from: 'cli.gradle'
|
||||
apply from: 'portable.gradle'
|
||||
apply from: 'proguard.gradle'
|
||||
apply from: 'github.gradle'
|
||||
|
||||
Vendored
+15
-1
@@ -14,6 +14,9 @@ def extLibrariesTasks = extModules.stream().map { it.getTasksByName('createExtOu
|
||||
|
||||
dependencies {
|
||||
implementation project(':app')
|
||||
if (fullVersion) {
|
||||
implementation project(':cli')
|
||||
}
|
||||
if (!useBundledJavaFx) {
|
||||
configurations.javafx.getAsFileTree().getFiles().forEach {
|
||||
implementation files(it)
|
||||
@@ -67,11 +70,22 @@ jlink {
|
||||
addOptions("--add-modules", "jdk.jdwp.agent")
|
||||
}
|
||||
|
||||
if (fullVersion) {
|
||||
addOptions("--add-modules", "io.xpipe.cli")
|
||||
}
|
||||
|
||||
launcher {
|
||||
moduleName = packageName(null)
|
||||
mainClass = packageName('Main')
|
||||
name = jpackageExecutableName
|
||||
jvmArgs = jpackageReleaseArguments
|
||||
jvmArgs = jpackageReleaseArguments + ["-Dio.xpipe.app.isDaemon=true"]
|
||||
}
|
||||
|
||||
secondaryLauncher {
|
||||
moduleName = packageName(null)
|
||||
mainClass = packageName('Main')
|
||||
name = "xpipe"
|
||||
jvmArgs = jpackageReleaseArguments + ["-Dio.xpipe.app.isCli=true"]
|
||||
}
|
||||
|
||||
jpackage {
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ Write-Host "$ProductName has been successfully installed. You should be able to
|
||||
Write-Host
|
||||
|
||||
# Use absolute path as we can't assume that the user has selected to put XPipe into the Path
|
||||
& "$env:LOCALAPPDATA\$ProductName\bin\xpipe.exe" open
|
||||
& "$env:LOCALAPPDATA\$ProductName\xpiped.exe" open
|
||||
|
||||
#endregion Install XPipe
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ testing {
|
||||
testTask.configure {
|
||||
workingDir = rootDir
|
||||
|
||||
jvmArgs += ["-Xmx2g"]
|
||||
jvmArgs += jvmRunArgs
|
||||
|
||||
def exts = files(project.allExtensions.stream().map(p -> p.getTasksByName('jar', true)[0].outputs.files.singleFile).toList())
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
extraJavaModuleInfo {
|
||||
module("de.vandermeer:asciitable", "de.vandermeer.asciitable") {
|
||||
exportAllPackages()
|
||||
requires('de.vandermeer.skb_interfaces')
|
||||
requires('de.vandermeer.ascii_utf_themes')
|
||||
requires('org.apache.commons.lang3')
|
||||
}
|
||||
|
||||
module("de.vandermeer:skb-interfaces", "de.vandermeer.skb_interfaces") {
|
||||
exportAllPackages()
|
||||
requires('org.apache.commons.lang3')
|
||||
}
|
||||
|
||||
module("de.vandermeer:ascii-utf-themes", "de.vandermeer.ascii_utf_themes") {
|
||||
exportAllPackages()
|
||||
requires('org.apache.commons.lang3')
|
||||
requires('de.vandermeer.skb_interfaces')
|
||||
}
|
||||
}
|
||||
|
||||
extraJavaModuleInfo {
|
||||
module("com.vladsch.flexmark:flexmark", "com.vladsch.flexmark") {
|
||||
mergeJar('com.vladsch.flexmark:flexmark-util')
|
||||
|
||||
@@ -18,7 +18,6 @@ testing {
|
||||
testTask.configure {
|
||||
workingDir = projectDir
|
||||
|
||||
jvmArgs += ["-Xmx2g"]
|
||||
jvmArgs += jvmRunArgs
|
||||
|
||||
def daemonArgs = Map.of(
|
||||
|
||||
Reference in New Issue
Block a user