Restructure proc module

This commit is contained in:
crschnick 2023-02-08 21:34:19 +00:00
parent d5c99ba49f
commit 51bbf8ad67
26 changed files with 159 additions and 159 deletions

View file

@ -84,8 +84,22 @@ The other modules make up the X-Pipe implementation and are licensed under GPL:
- [app](app) - Contains the X-Pipe daemon implementation and the X-Pipe desktop application code - [app](app) - Contains the X-Pipe daemon implementation and the X-Pipe desktop application code
- [cli](cli) - The X-Pipe CLI implementation, a GraalVM native image application - [cli](cli) - The X-Pipe CLI implementation, a GraalVM native image application
- [dist](dist) - Tools to create a distributable package of X-Pipe - [dist](dist) - Tools to create a distributable package of X-Pipe
- [ext](ext) - Available X-Pipe extensions. Note that essentially every feature is implemented as an extension - [ext](ext) - Available X-Pipe extensions. Essentially every feature is implemented as an extension
### Open source model
X-Pipe utilizes an open core model, which essentially means that
the main application core is open source while certain other components are not.
In this case these non open source components are planned to be future parts of a potential commercialization.
Furthermore, some tests and especially test environments and that run on private servers
are also not included in this repository (Don't want to leak server information).
Finally, scripts and workflows to create signed executables and installers
are also not included to prevent attackers from easily impersonating the shipping the X-Pipe application malware.
The license model is chosen in such a way that you are
able to use and integrate X-Pipe within your application through the MIT-licensed API.
In any other case where you plan to contribute to the X-Pipe platform itself, which is GPL licensed,
I would still have to figure out how to exactly handle these kinds of contributions.
## Development ## Development

View file

@ -89,7 +89,7 @@ List<String> jvmRunArgs = [
"--add-exports", "org.apache.commons.lang3/org.apache.commons.lang3.math=io.xpipe.extension", "--add-exports", "org.apache.commons.lang3/org.apache.commons.lang3.math=io.xpipe.extension",
"--add-opens", "java.base/java.lang.reflect=com.jfoenix", "--add-opens", "java.base/java.lang.reflect=com.jfoenix",
"--add-opens", "java.base/java.lang.reflect=com.jfoenix", "--add-opens", "java.base/java.lang.reflect=com.jfoenix",
"--add-opens", "java.base/java.lang=io.xpipe.app", "--add-opens", "java.base/java.lang=io.xpipe.core",
"--add-opens", "com.dustinredmond.fxtrayicon/com.dustinredmond.fxtrayicon=io.xpipe.app", "--add-opens", "com.dustinredmond.fxtrayicon/com.dustinredmond.fxtrayicon=io.xpipe.app",
"--add-opens", "net.synedra.validatorfx/net.synedra.validatorfx=io.xpipe.extension", "--add-opens", "net.synedra.validatorfx/net.synedra.validatorfx=io.xpipe.extension",
"-Xmx8g", "-Xmx8g",

View file

@ -2,6 +2,7 @@ package io.xpipe.app.core;
import io.xpipe.app.Main; import io.xpipe.app.Main;
import io.xpipe.app.comp.AppLayoutComp; import io.xpipe.app.comp.AppLayoutComp;
import io.xpipe.core.process.OsType;
import io.xpipe.extension.event.ErrorEvent; import io.xpipe.extension.event.ErrorEvent;
import io.xpipe.extension.event.TrackEvent; import io.xpipe.extension.event.TrackEvent;
import io.xpipe.extension.fxcomps.util.PlatformThread; import io.xpipe.extension.fxcomps.util.PlatformThread;
@ -10,7 +11,6 @@ import javafx.application.Platform;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.apache.commons.lang3.SystemUtils;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.*; import java.awt.*;
@ -38,7 +38,7 @@ public class App extends Application {
// Set dock icon explicitly on mac // Set dock icon explicitly on mac
// This is necessary in case X-Pipe was started through a script as it will have no icon otherwise // This is necessary in case X-Pipe was started through a script as it will have no icon otherwise
if (SystemUtils.IS_OS_MAC) { if (OsType.getLocal().equals(OsType.MACOS)) {
try { try {
var iconUrl = Main.class.getResourceAsStream("resources/img/logo.png"); var iconUrl = Main.class.getResourceAsStream("resources/img/logo.png");
if (iconUrl != null) { if (iconUrl != null) {

View file

@ -77,7 +77,7 @@ public class LauncherCommand implements Callable<Integer> {
OpenExchange.Request.builder().arguments(inputs).build()); OpenExchange.Request.builder().arguments(inputs).build());
} }
if (OsType.getLocal().equals(OsType.MAC)) { if (OsType.getLocal().equals(OsType.MACOS)) {
Desktop.getDesktop().setOpenURIHandler(e -> { Desktop.getDesktop().setOpenURIHandler(e -> {
con.performSimpleExchange( con.performSimpleExchange(
OpenExchange.Request.builder().arguments(List.of(e.getURI().toString())).build()); OpenExchange.Request.builder().arguments(List.of(e.getURI().toString())).build());
@ -120,7 +120,7 @@ public class LauncherCommand implements Callable<Integer> {
LauncherInput.handle(inputs); LauncherInput.handle(inputs);
// URL open operations have to be handled in a special way on macOS! // URL open operations have to be handled in a special way on macOS!
if (OsType.getLocal().equals(OsType.MAC)) { if (OsType.getLocal().equals(OsType.MACOS)) {
Desktop.getDesktop().setOpenURIHandler(e -> { Desktop.getDesktop().setOpenURIHandler(e -> {
LauncherInput.handle(List.of(e.getURI().toString())); LauncherInput.handle(List.of(e.getURI().toString()));
}); });

View file

@ -57,7 +57,7 @@ public abstract class ExternalApplicationType implements PrefsChoiceValue {
@Override @Override
public boolean isSelectable() { public boolean isSelectable() {
return OsType.getLocal().equals(OsType.MAC); return OsType.getLocal().equals(OsType.MACOS);
} }
@Override @Override

View file

@ -5,7 +5,6 @@ import io.xpipe.core.process.ShellTypes;
import io.xpipe.extension.prefs.PrefsChoiceValue; import io.xpipe.extension.prefs.PrefsChoiceValue;
import io.xpipe.extension.util.ApplicationHelper; import io.xpipe.extension.util.ApplicationHelper;
import io.xpipe.extension.util.WindowsRegistry; import io.xpipe.extension.util.WindowsRegistry;
import org.apache.commons.lang3.SystemUtils;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
@ -38,13 +37,9 @@ public interface ExternalEditorType extends PrefsChoiceValue {
@Override @Override
protected Optional<Path> determinePath() { protected Optional<Path> determinePath() {
Optional<String> launcherDir = Optional.empty(); Optional<String> launcherDir;
if (SystemUtils.IS_OS_WINDOWS) { launcherDir = WindowsRegistry.readString(WindowsRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Notepad++", null)
launcherDir = WindowsRegistry.readString( .map(p -> p + "\\notepad++.exe");
WindowsRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Notepad++", null)
.map(p -> p + "\\notepad++.exe");
}
return launcherDir.map(Path::of); return launcherDir.map(Path::of);
} }
}; };
@ -71,7 +66,8 @@ public interface ExternalEditorType extends PrefsChoiceValue {
@Override @Override
public void launch(Path file) throws Exception { public void launch(Path file) throws Exception {
ApplicationHelper.executeLocalApplication(List.of("open", "-a", getApplicationPath().orElseThrow().toString(), file.toString())); ApplicationHelper.executeLocalApplication(
List.of("open", "-a", getApplicationPath().orElseThrow().toString(), file.toString()));
} }
} }
@ -92,7 +88,7 @@ public interface ExternalEditorType extends PrefsChoiceValue {
var format = customCommand.contains("$file") ? customCommand : customCommand + " $file"; var format = customCommand.contains("$file") ? customCommand : customCommand + " $file";
var fileString = file.toString().contains(" ") ? "\"" + file + "\"" : file.toString(); var fileString = file.toString().contains(" ") ? "\"" + file + "\"" : file.toString();
ApplicationHelper.executeLocalApplication(format.replace("$file",fileString)); ApplicationHelper.executeLocalApplication(format.replace("$file", fileString));
} }
@Override @Override
@ -108,7 +104,6 @@ public interface ExternalEditorType extends PrefsChoiceValue {
public void launch(Path file) throws Exception; public void launch(Path file) throws Exception;
public static class LinuxPathType extends ExternalApplicationType.PathApplication implements ExternalEditorType { public static class LinuxPathType extends ExternalApplicationType.PathApplication implements ExternalEditorType {
public LinuxPathType(String id, String command) { public LinuxPathType(String id, String command) {
@ -127,7 +122,8 @@ public interface ExternalEditorType extends PrefsChoiceValue {
} }
} }
public abstract static class WindowsFullPathType extends ExternalApplicationType.WindowsFullPathType implements ExternalEditorType { public abstract static class WindowsFullPathType extends ExternalApplicationType.WindowsFullPathType
implements ExternalEditorType {
public WindowsFullPathType(String id) { public WindowsFullPathType(String id) {
super(id); super(id);
@ -147,23 +143,23 @@ public interface ExternalEditorType extends PrefsChoiceValue {
public static final List<ExternalEditorType> WINDOWS_EDITORS = List.of(VSCODE, NOTEPADPLUSPLUS_WINDOWS, NOTEPAD); public static final List<ExternalEditorType> WINDOWS_EDITORS = List.of(VSCODE, NOTEPADPLUSPLUS_WINDOWS, NOTEPAD);
public static final List<LinuxPathType> LINUX_EDITORS = public static final List<LinuxPathType> LINUX_EDITORS =
List.of(VSCODE_LINUX, NOTEPADPLUSPLUS_LINUX, KATE, GEDIT, PLUMA, LEAFPAD, MOUSEPAD); List.of(VSCODE_LINUX, NOTEPADPLUSPLUS_LINUX, KATE, GEDIT, PLUMA, LEAFPAD, MOUSEPAD);
public static final List<ExternalEditorType> MACOS_EDITORS = public static final List<ExternalEditorType> MACOS_EDITORS = List.of(VSCODE_MACOS, SUBLIME_MACOS, TEXT_EDIT);
List.of(VSCODE_MACOS, SUBLIME_MACOS, TEXT_EDIT);
public static final List<ExternalEditorType> ALL = ((Supplier<List<ExternalEditorType>>) () -> { public static final List<ExternalEditorType> ALL = ((Supplier<List<ExternalEditorType>>) () -> {
var all = new ArrayList<ExternalEditorType>(); var all = new ArrayList<ExternalEditorType>();
if (OsType.getLocal().equals(OsType.WINDOWS)) { if (OsType.getLocal().equals(OsType.WINDOWS)) {
all.addAll(WINDOWS_EDITORS); all.addAll(WINDOWS_EDITORS);
} }
if (OsType.getLocal().equals(OsType.LINUX)) { if (OsType.getLocal().equals(OsType.LINUX)) {
all.addAll(LINUX_EDITORS); all.addAll(LINUX_EDITORS);
} }
if (OsType.getLocal().equals(OsType.MAC)) { if (OsType.getLocal().equals(OsType.MACOS)) {
all.addAll(MACOS_EDITORS); all.addAll(MACOS_EDITORS);
} }
all.add(CUSTOM); all.add(CUSTOM);
return all; return all;
}).get(); })
.get();
public static void detectDefault() { public static void detectDefault() {
var typeProperty = AppPrefs.get().externalEditor; var typeProperty = AppPrefs.get().externalEditor;
@ -190,13 +186,13 @@ public interface ExternalEditorType extends PrefsChoiceValue {
} }
} else { } else {
typeProperty.set(LINUX_EDITORS.stream() typeProperty.set(LINUX_EDITORS.stream()
.filter(externalEditorType -> externalEditorType.isAvailable()) .filter(externalEditorType -> externalEditorType.isAvailable())
.findFirst() .findFirst()
.orElse(null)); .orElse(null));
} }
} }
if (OsType.getLocal().equals(OsType.MAC)) { if (OsType.getLocal().equals(OsType.MACOS)) {
typeProperty.set(MACOS_EDITORS.stream() typeProperty.set(MACOS_EDITORS.stream()
.filter(externalEditorType -> externalEditorType.isAvailable()) .filter(externalEditorType -> externalEditorType.isAvailable())
.findFirst() .findFirst()

View file

@ -121,6 +121,7 @@ public class DataStoreEntry extends StorageElement {
var information = Optional.ofNullable(json.get("information")) var information = Optional.ofNullable(json.get("information"))
.map(JsonNode::textValue) .map(JsonNode::textValue)
.orElse(null); .orElse(null);
var lastUsed = Instant.parse(json.required("lastUsed").textValue()); var lastUsed = Instant.parse(json.required("lastUsed").textValue());
var lastModified = Instant.parse(json.required("lastModified").textValue()); var lastModified = Instant.parse(json.required("lastModified").textValue());
var configuration = Optional.ofNullable(json.get("configuration")) var configuration = Optional.ofNullable(json.get("configuration"))

View file

@ -1,16 +1,14 @@
package io.xpipe.app.storage; package io.xpipe.app.storage;
import io.xpipe.core.util.XPipeTempDirectory; import io.xpipe.core.util.XPipeSession;
import io.xpipe.extension.event.ErrorEvent; import io.xpipe.extension.event.ErrorEvent;
import io.xpipe.extension.event.TrackEvent; import io.xpipe.extension.event.TrackEvent;
import lombok.NonNull; import lombok.NonNull;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.SystemUtils;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -22,44 +20,7 @@ public class StandardStorage extends DataStorage {
private DataSourceCollection recovery; private DataSourceCollection recovery;
private boolean isNewSession() { private boolean isNewSession() {
try { return XPipeSession.get().isNewSystemSession();
if (SystemUtils.IS_OS_WINDOWS) {
var sessionFile = dir.resolve("session");
if (!Files.exists(sessionFile)) {
return true;
}
var lastSessionEndTime = Instant.parse(Files.readString(sessionFile));
var pf = Path.of("C:\\pagefile.sys");
var lastBootTime = Files.getLastModifiedTime(pf).toInstant();
return lastSessionEndTime.isBefore(lastBootTime);
} else {
var sessionFile = XPipeTempDirectory.getLocal().resolve("xpipe_session");
return !Files.exists(sessionFile);
}
} catch (Exception ex) {
ErrorEvent.fromThrowable(ex).omitted(true).build().handle();
return true;
}
}
private void writeSessionInfo() {
try {
if (SystemUtils.IS_OS_WINDOWS) {
var sessionFile = dir.resolve("session");
var now = Instant.now().toString();
Files.writeString(sessionFile, now);
} else {
var sessionFile = XPipeTempDirectory.getLocal().resolve("xpipe_session");
if (!Files.exists(sessionFile)) {
Files.createFile(sessionFile);
}
}
} catch (Exception ex) {
ErrorEvent.fromThrowable(ex).omitted(true).build().handle();
}
} }
private void deleteLeftovers() { private void deleteLeftovers() {
@ -322,8 +283,6 @@ public class StandardStorage extends DataStorage {
} }
deleteLeftovers(); deleteLeftovers();
writeSessionInfo();
} }
@Override @Override

View file

@ -63,7 +63,7 @@ public class AppInstaller {
return Files.exists(Path.of("/etc/debian_version")) ? new InstallerAssetType.Debian() : new InstallerAssetType.Rpm(); return Files.exists(Path.of("/etc/debian_version")) ? new InstallerAssetType.Debian() : new InstallerAssetType.Rpm();
} }
if (OsType.getLocal().equals(OsType.MAC)) { if (OsType.getLocal().equals(OsType.MACOS)) {
return new InstallerAssetType.Pkg(); return new InstallerAssetType.Pkg();
} }
@ -82,7 +82,7 @@ public class AppInstaller {
} }
} }
if (p.getOsType().equals(OsType.MAC)) { if (p.getOsType().equals(OsType.MACOS)) {
return new InstallerAssetType.Pkg(); return new InstallerAssetType.Pkg();
} }

View file

@ -6,7 +6,7 @@ import io.xpipe.app.core.AppExtensionManager;
import io.xpipe.app.core.AppProperties; import io.xpipe.app.core.AppProperties;
import io.xpipe.app.core.mode.OperationMode; import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.impl.ProcessControlProvider; import io.xpipe.core.process.ProcessControlProvider;
import io.xpipe.core.util.XPipeSession; import io.xpipe.core.util.XPipeSession;
import io.xpipe.extension.event.ErrorEvent; import io.xpipe.extension.event.ErrorEvent;
import io.xpipe.extension.event.TrackEvent; import io.xpipe.extension.event.TrackEvent;

View file

@ -112,9 +112,7 @@ public abstract class Charsetter {
if (store instanceof FileStore fileStore && fileStore.getFileSystem() instanceof MachineStore m) { if (store instanceof FileStore fileStore && fileStore.getFileSystem() instanceof MachineStore m) {
if (result.getNewLine() == null) { if (result.getNewLine() == null) {
try (var pc = m.create().start()) { result = new Result(result.getCharset(), m.getShellType() != null ? m.getShellType().getNewLine() : null);
result = new Result(result.getCharset(), pc.getShellType().getNewLine());
}
} }
} }

View file

@ -1,6 +1,7 @@
package io.xpipe.core.impl; package io.xpipe.core.impl;
import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.core.process.ProcessControlProvider;
import io.xpipe.core.process.ShellProcessControl; import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.store.FileSystemStore; import io.xpipe.core.store.FileSystemStore;
import io.xpipe.core.store.MachineStore; import io.xpipe.core.store.MachineStore;
@ -47,7 +48,7 @@ public class LocalStore extends JacksonizedValue implements FileSystemStore, Mac
} }
@Override @Override
public ShellProcessControl create() { public ShellProcessControl createControl() {
return ProcessControlProvider.createLocal(); return ProcessControlProvider.createLocal();
} }

View file

@ -1,50 +0,0 @@
package io.xpipe.core.impl;
import io.xpipe.core.process.CommandProcessControl;
import io.xpipe.core.process.ShellProcessControl;
import lombok.NonNull;
import java.util.List;
import java.util.ServiceLoader;
import java.util.function.BiFunction;
import java.util.function.Function;
public abstract class ProcessControlProvider {
private static List<ProcessControlProvider> INSTANCES;
public static void init(ModuleLayer layer) {
INSTANCES = ServiceLoader.load(layer, ProcessControlProvider.class)
.stream().map(localProcessControlProviderProvider -> localProcessControlProviderProvider.get()).toList();
}
public static ShellProcessControl createLocal() {
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.createLocalProcessControl()).findFirst().orElseThrow();
}
public static ShellProcessControl createSub(
ShellProcessControl parent,
@NonNull Function<ShellProcessControl, String> commandFunction,
BiFunction<ShellProcessControl, String, String> terminalCommand) {
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.sub(parent, commandFunction, terminalCommand)).findFirst().orElseThrow();
}
public static CommandProcessControl createCommand(
ShellProcessControl parent,
@NonNull Function<ShellProcessControl, String> command,
Function<ShellProcessControl, String> terminalCommand) {
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.command(parent, command, terminalCommand)).findFirst().orElseThrow();
}
public abstract ShellProcessControl sub(
ShellProcessControl parent,
@NonNull Function<ShellProcessControl, String> commandFunction,
BiFunction<ShellProcessControl, String, String> terminalCommand);
public abstract CommandProcessControl command(
ShellProcessControl parent,
@NonNull Function<ShellProcessControl, String> command,
Function<ShellProcessControl, String> terminalCommand);
public abstract ShellProcessControl createLocalProcessControl();
}

View file

@ -7,12 +7,12 @@ public interface OsType {
Windows WINDOWS = new Windows(); Windows WINDOWS = new Windows();
Linux LINUX = new Linux(); Linux LINUX = new Linux();
Mac MAC = new Mac(); MacOs MACOS = new MacOs();
public static OsType getLocal() { public static OsType getLocal() {
String osName = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH); String osName = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
if ((osName.contains("mac")) || (osName.contains("darwin"))) { if ((osName.contains("mac")) || (osName.contains("darwin"))) {
return MAC; return MACOS;
} else if (osName.contains("win")) { } else if (osName.contains("win")) {
return WINDOWS; return WINDOWS;
} else if (osName.contains("nux")) { } else if (osName.contains("nux")) {
@ -124,7 +124,7 @@ public interface OsType {
} }
} }
static class Mac implements OsType { static class MacOs implements OsType {
@Override @Override
public String getTempDirectory(ShellProcessControl pc) throws Exception { public String getTempDirectory(ShellProcessControl pc) throws Exception {

View file

@ -1,6 +1,58 @@
package io.xpipe.core.process; package io.xpipe.core.process;
import lombok.NonNull;
import java.util.List;
import java.util.Objects;
import java.util.ServiceLoader;
import java.util.function.BiFunction;
import java.util.function.Function;
public abstract class ProcessControlProvider { public abstract class ProcessControlProvider {
public abstract ProcessControl local(); private static List<ProcessControlProvider> INSTANCES;
public static void init(ModuleLayer layer) {
INSTANCES = ServiceLoader.load(layer, ProcessControlProvider.class)
.stream().map(localProcessControlProviderProvider -> localProcessControlProviderProvider.get()).toList();
}
public static ShellProcessControl createLocal() {
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.createLocalProcessControl()).findFirst().orElseThrow();
}
public static ShellProcessControl createSub(
ShellProcessControl parent,
@NonNull Function<ShellProcessControl, String> commandFunction,
BiFunction<ShellProcessControl, String, String> terminalCommand) {
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.sub(parent, commandFunction, terminalCommand)).filter(
Objects::nonNull).findFirst().orElseThrow();
}
public static CommandProcessControl createCommand(
ShellProcessControl parent,
@NonNull Function<ShellProcessControl, String> command,
Function<ShellProcessControl, String> terminalCommand) {
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.command(parent, command, terminalCommand)).filter(
Objects::nonNull).findFirst().orElseThrow();
}
public static ShellProcessControl createSsh(Object sshStore) {
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.createSshControl(sshStore)).filter(
Objects::nonNull).findFirst().orElseThrow();
}
public abstract ShellProcessControl sub(
ShellProcessControl parent,
@NonNull Function<ShellProcessControl, String> commandFunction,
BiFunction<ShellProcessControl, String, String> terminalCommand);
public abstract CommandProcessControl command(
ShellProcessControl parent,
@NonNull Function<ShellProcessControl, String> command,
Function<ShellProcessControl, String> terminalCommand);
public abstract ShellProcessControl createLocalProcessControl();
public abstract ShellProcessControl createSshControl(Object sshStore);
} }

View file

@ -6,11 +6,14 @@ import lombok.NonNull;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
public interface ShellProcessControl extends ProcessControl { public interface ShellProcessControl extends ProcessControl {
void onInit(Consumer<ShellProcessControl> pc);
String prepareTerminalOpen() throws Exception; String prepareTerminalOpen() throws Exception;
String prepareIntermediateTerminalOpen(String content) throws Exception; String prepareIntermediateTerminalOpen(String content) throws Exception;

View file

@ -2,10 +2,14 @@ package io.xpipe.core.store;
import io.xpipe.core.charsetter.Charsetter; import io.xpipe.core.charsetter.Charsetter;
import io.xpipe.core.impl.LocalStore; import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellProcessControl; import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.process.ShellType; import io.xpipe.core.process.ShellType;
public interface ShellStore extends DataStore { import java.nio.charset.Charset;
public interface ShellStore extends DataStore, StatefulDataStore
{
public static MachineStore local() { public static MachineStore local() {
return new LocalStore(); return new LocalStore();
@ -21,7 +25,28 @@ public interface ShellStore extends DataStore {
return s instanceof LocalStore; return s instanceof LocalStore;
} }
ShellProcessControl create(); default ShellProcessControl create() {
var pc = createControl();
pc.onInit(processControl -> {
setState("type", processControl.getShellType());
setState("os", processControl.getOsType());
setState("charset", processControl.getCharset());
});
return pc;
}
default ShellType getShellType() {
return getState("type", ShellType.class, null);
}
default OsType getOsType() {
return getState("os", OsType.class, null);
}
default Charset getCharset() {
return getState("charset", Charset.class, null);
}
ShellProcessControl createControl();
public default ShellType determineType() throws Exception { public default ShellType determineType() throws Exception {
try (var pc = create().start()) { try (var pc = create().start()) {

View file

@ -20,7 +20,7 @@ public class XPipeInstallation {
if (OsType.getLocal().equals(OsType.LINUX)) { if (OsType.getLocal().equals(OsType.LINUX)) {
return "nohup \"" + installationBase + "/app/bin/xpiped\" --mode " + mode.getDisplayName() + suffix return "nohup \"" + installationBase + "/app/bin/xpiped\" --mode " + mode.getDisplayName() + suffix
+ " & disown"; + " & disown";
} else if (OsType.getLocal().equals(OsType.MAC)) { } else if (OsType.getLocal().equals(OsType.MACOS)) {
return "open \"" + installationBase + "\" --args --mode " + mode.getDisplayName() + suffix; return "open \"" + installationBase + "\" --args --mode " + mode.getDisplayName() + suffix;
} }
@ -55,7 +55,7 @@ public class XPipeInstallation {
public static boolean isInstallationDistribution() { public static boolean isInstallationDistribution() {
var base = getLocalInstallationBasePath(); var base = getLocalInstallationBasePath();
if (OsType.getLocal().equals(OsType.MAC)) { if (OsType.getLocal().equals(OsType.MACOS)) {
if (!base.toString().equals(getLocalDefaultInstallationBasePath(false))) { if (!base.toString().equals(getLocalDefaultInstallationBasePath(false))) {
return false; return false;
} }
@ -93,13 +93,13 @@ public class XPipeInstallation {
public static Path getLocalExtensionsDirectory() { public static Path getLocalExtensionsDirectory() {
Path path = getLocalInstallationBasePath(); Path path = getLocalInstallationBasePath();
return OsType.getLocal().equals(OsType.MAC) return OsType.getLocal().equals(OsType.MACOS)
? path.resolve("Contents").resolve("Resources").resolve("extensions") ? path.resolve("Contents").resolve("Resources").resolve("extensions")
: path.resolve("app").resolve("extensions"); : path.resolve("app").resolve("extensions");
} }
private static Path getLocalInstallationBasePathForJavaExecutable(Path executable) { private static Path getLocalInstallationBasePathForJavaExecutable(Path executable) {
if (OsType.getLocal().equals(OsType.MAC)) { if (OsType.getLocal().equals(OsType.MACOS)) {
return executable return executable
.getParent() .getParent()
.getParent() .getParent()
@ -115,7 +115,7 @@ public class XPipeInstallation {
} }
private static Path getLocalInstallationBasePathForDaemonExecutable(Path executable) { private static Path getLocalInstallationBasePathForDaemonExecutable(Path executable) {
if (OsType.getLocal().equals(OsType.MAC)) { if (OsType.getLocal().equals(OsType.MACOS)) {
return executable.getParent().getParent().getParent(); return executable.getParent().getParent().getParent();
} else if (OsType.getLocal().equals(OsType.LINUX)) { } else if (OsType.getLocal().equals(OsType.LINUX)) {
return executable.getParent().getParent().getParent(); return executable.getParent().getParent().getParent();
@ -138,7 +138,7 @@ public class XPipeInstallation {
return defaultInstallation; return defaultInstallation;
} }
if (OsType.getLocal().equals(OsType.MAC)) { if (OsType.getLocal().equals(OsType.MACOS)) {
return FileNames.getParent(FileNames.getParent(FileNames.getParent(cliExecutable))); return FileNames.getParent(FileNames.getParent(FileNames.getParent(cliExecutable)));
} else { } else {
return FileNames.getParent(FileNames.getParent(cliExecutable)); return FileNames.getParent(FileNames.getParent(cliExecutable));

View file

@ -26,7 +26,7 @@ public class XPipeTempDirectory {
if (!proc.executeBooleanSimpleCommand(proc.getShellType().getFileExistsCommand(dir))) { if (!proc.executeBooleanSimpleCommand(proc.getShellType().getFileExistsCommand(dir))) {
proc.executeSimpleCommand(proc.getShellType().flatten(proc.getShellType().getMkdirsCommand(dir)), "Unable to access or create temporary directory " + dir); proc.executeSimpleCommand(proc.getShellType().flatten(proc.getShellType().getMkdirsCommand(dir)), "Unable to access or create temporary directory " + dir);
if (proc.getOsType().equals(OsType.LINUX) || proc.getOsType().equals(OsType.MAC)) { if (proc.getOsType().equals(OsType.LINUX) || proc.getOsType().equals(OsType.MACOS)) {
proc.executeSimpleCommand("chmod -f 777 \"" + dir + "\""); proc.executeSimpleCommand("chmod -f 777 \"" + dir + "\"");
} }
} }

View file

@ -1,4 +1,4 @@
import io.xpipe.core.impl.ProcessControlProvider; import io.xpipe.core.process.ProcessControlProvider;
import io.xpipe.core.source.WriteMode; import io.xpipe.core.source.WriteMode;
import io.xpipe.core.util.CoreJacksonModule; import io.xpipe.core.util.CoreJacksonModule;

View file

@ -3,7 +3,6 @@ package io.xpipe.ext.pdx.parser;
import io.xpipe.core.data.node.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.TupleNode; import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.node.ValueNode; import io.xpipe.core.data.node.ValueNode;
import org.apache.commons.lang3.SystemUtils;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
@ -40,7 +39,7 @@ public final class TextFormatParser {
public static TextFormatParser eu4() { public static TextFormatParser eu4() {
return new TextFormatParser( return new TextFormatParser(
SystemUtils.IS_OS_MAC ? StandardCharsets.UTF_8 : Charset.forName("windows-1252"), Charset.forName("windows-1252"),
TaggedNodes.NO_TAGS, TaggedNodes.NO_TAGS,
s -> s.equals("map_area_data")); s -> s.equals("map_area_data"));
} }
@ -59,14 +58,14 @@ public final class TextFormatParser {
public static TextFormatParser ck2() { public static TextFormatParser ck2() {
return new TextFormatParser( return new TextFormatParser(
SystemUtils.IS_OS_MAC ? StandardCharsets.UTF_8 : Charset.forName("windows-1252"), Charset.forName("windows-1252"),
TaggedNodes.NO_TAGS, TaggedNodes.NO_TAGS,
s -> false); s -> false);
} }
public static TextFormatParser vic2() { public static TextFormatParser vic2() {
return new TextFormatParser( return new TextFormatParser(
SystemUtils.IS_OS_MAC ? StandardCharsets.UTF_8 : Charset.forName("windows-1252"), Charset.forName("windows-1252"),
TaggedNodes.NO_TAGS, TaggedNodes.NO_TAGS,
s -> false); s -> false);
} }

1
ext/procx/build.gradle Normal file
View file

@ -0,0 +1 @@
plugins { id 'java' }

View file

@ -0,0 +1 @@
module io.xpipe.ext.procx {}

View file

@ -79,7 +79,7 @@ public interface DataStoreProvider {
} }
default String getModuleName() { default String getModuleName() {
var n = getClass().getPackageName(); var n = getClass().getModule().getName();
var i = n.lastIndexOf('.'); var i = n.lastIndexOf('.');
return i != -1 ? n.substring(i + 1) : n; return i != -1 ? n.substring(i + 1) : n;
} }

View file

@ -1,7 +1,7 @@
package io.xpipe.extension; package io.xpipe.extension;
import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.NamedType;
import io.xpipe.core.impl.ProcessControlProvider; import io.xpipe.core.process.ProcessControlProvider;
import io.xpipe.core.util.JacksonMapper; import io.xpipe.core.util.JacksonMapper;
import io.xpipe.core.util.ProxyFunction; import io.xpipe.core.util.ProxyFunction;
import io.xpipe.extension.event.TrackEvent; import io.xpipe.extension.event.TrackEvent;

View file

@ -42,7 +42,7 @@ public interface XPipeDistributionType {
@Override @Override
public boolean supportsURLs() { public boolean supportsURLs() {
return OsType.getLocal().equals(OsType.MAC); return OsType.getLocal().equals(OsType.MACOS);
} }
@Override @Override