mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-25 09:00:26 +00:00
Add some more store commands, add dialog helpers, and small fixes
This commit is contained in:
parent
775a046e66
commit
e0266fec6b
12 changed files with 202 additions and 30 deletions
|
@ -0,0 +1,33 @@
|
||||||
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
import io.xpipe.beacon.RequestMessage;
|
||||||
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
|
import io.xpipe.core.dialog.DialogReference;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.Value;
|
||||||
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
public class EditStoreExchange implements MessageExchange {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "editEntry";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Jacksonized
|
||||||
|
@Builder
|
||||||
|
@Value
|
||||||
|
public static class Request implements RequestMessage {
|
||||||
|
@NonNull
|
||||||
|
String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Jacksonized
|
||||||
|
@Builder
|
||||||
|
@Value
|
||||||
|
public static class Response implements ResponseMessage {
|
||||||
|
@NonNull DialogReference dialog;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,11 +13,11 @@ import lombok.extern.jackson.Jacksonized;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class ProviderListExchange implements MessageExchange {
|
public class SourceProviderListExchange implements MessageExchange {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return "providerList";
|
return "sourceProviderList";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
|
@ -0,0 +1,33 @@
|
||||||
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
|
import io.xpipe.beacon.RequestMessage;
|
||||||
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
|
import io.xpipe.beacon.exchange.data.ProviderEntry;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.Value;
|
||||||
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class StoreProviderListExchange implements MessageExchange {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "storeProviderList";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Jacksonized
|
||||||
|
@Builder
|
||||||
|
@Value
|
||||||
|
public static class Request implements RequestMessage {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Jacksonized
|
||||||
|
@Builder
|
||||||
|
@Value
|
||||||
|
public static class Response implements ResponseMessage {
|
||||||
|
@NonNull List<ProviderEntry> entries;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,8 @@ module io.xpipe.beacon {
|
||||||
|
|
||||||
uses MessageExchange;
|
uses MessageExchange;
|
||||||
provides io.xpipe.beacon.exchange.MessageExchange with
|
provides io.xpipe.beacon.exchange.MessageExchange with
|
||||||
|
EditStoreExchange,
|
||||||
|
StoreProviderListExchange,
|
||||||
ListCollectionsExchange,
|
ListCollectionsExchange,
|
||||||
ListEntriesExchange,
|
ListEntriesExchange,
|
||||||
ModeExchange,
|
ModeExchange,
|
||||||
|
@ -45,7 +47,7 @@ module io.xpipe.beacon {
|
||||||
RemoveCollectionExchange,
|
RemoveCollectionExchange,
|
||||||
RenameCollectionExchange,
|
RenameCollectionExchange,
|
||||||
RenameEntryExchange,
|
RenameEntryExchange,
|
||||||
ProviderListExchange,
|
SourceProviderListExchange,
|
||||||
ConvertExchange,
|
ConvertExchange,
|
||||||
QueryRawDataExchange,
|
QueryRawDataExchange,
|
||||||
QueryTableDataExchange,
|
QueryTableDataExchange,
|
||||||
|
|
|
@ -6,7 +6,6 @@ import lombok.Value;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A store whose contents are stored in memory.
|
* A store whose contents are stored in memory.
|
||||||
|
@ -22,10 +21,6 @@ public class InMemoryStore implements StreamDataStore {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InMemoryStore(String s) {
|
|
||||||
value = s.getBytes(StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLocalToApplication() {
|
public boolean isLocalToApplication() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -23,22 +22,19 @@ public class LocalStore extends StandardShellStore implements MachineFileStore {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class LocalProcessControl extends ProcessControl {
|
class LocalProcessControl extends ProcessControl {
|
||||||
|
|
||||||
private final List<Secret> input;
|
private final List<Secret> input;
|
||||||
private final ProcessBuilder builder;
|
|
||||||
private final Integer timeout;
|
private final Integer timeout;
|
||||||
|
private final List<String> command;
|
||||||
|
private Charset charset;
|
||||||
|
|
||||||
private Process process;
|
private Process process;
|
||||||
|
|
||||||
LocalProcessControl(List<Secret> input, List<String> cmd, Integer timeout) {
|
LocalProcessControl(List<Secret> input, List<String> cmd, Integer timeout) {
|
||||||
this.input = input;
|
this.input = input;
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
var l = new ArrayList<String>();
|
this.command = cmd;
|
||||||
l.add("cmd");
|
|
||||||
l.add("/c");
|
|
||||||
l.addAll(cmd);
|
|
||||||
builder = new ProcessBuilder(l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream createInputStream() {
|
private InputStream createInputStream() {
|
||||||
|
@ -47,8 +43,12 @@ public class LocalStore extends StandardShellStore implements MachineFileStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() throws IOException {
|
public void start() throws Exception {
|
||||||
|
var type = LocalStore.this.determineType();
|
||||||
|
var l = type.switchTo(command);
|
||||||
|
var builder = new ProcessBuilder(l);
|
||||||
process = builder.start();
|
process = builder.start();
|
||||||
|
charset = type.getCharset();
|
||||||
|
|
||||||
var t = new Thread(() -> {
|
var t = new Thread(() -> {
|
||||||
try (var inputStream = createInputStream()){
|
try (var inputStream = createInputStream()){
|
||||||
|
@ -84,7 +84,7 @@ public class LocalStore extends StandardShellStore implements MachineFileStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Charset getCharset() {
|
public Charset getCharset() {
|
||||||
return StandardCharsets.US_ASCII;
|
return charset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getTimeout() {
|
public Integer getTimeout() {
|
||||||
|
@ -126,6 +126,6 @@ public class LocalStore extends StandardShellStore implements MachineFileStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ShellType determineType() throws Exception {
|
public ShellType determineType() throws Exception {
|
||||||
return ShellTypes.determine(this);
|
return ShellTypes.getDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,11 +72,13 @@ public interface DataStoreProvider {
|
||||||
return getModuleName() + ":" + getId() + "_icon.png";
|
return getModuleName() + ":" + getId() + "_icon.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
default Dialog dialogForString(String s) {
|
DataStore storeForString(String s);
|
||||||
|
|
||||||
|
default Dialog dialogForStore(DataStore store) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
default Dialog defaultDialog() {
|
default DataStore defaultStore() {
|
||||||
throw new ExtensionException("CLI Dialog not implemented by provider");
|
throw new ExtensionException("CLI Dialog not implemented by provider");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,15 @@ public class DataStoreProviders {
|
||||||
throw new IllegalStateException("Not initialized");
|
throw new IllegalStateException("Not initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ALL.stream().map(d -> d.dialogForString(s)).filter(Objects::nonNull).findAny();
|
return ALL.stream().map(d -> {
|
||||||
|
var store = d.storeForString(s);
|
||||||
|
if (store != null) {
|
||||||
|
return d.dialogForStore(store);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).filter(Objects::nonNull).findAny();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
83
extension/src/main/java/io/xpipe/extension/DialogHelper.java
Normal file
83
extension/src/main/java/io/xpipe/extension/DialogHelper.java
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package io.xpipe.extension;
|
||||||
|
|
||||||
|
import io.xpipe.core.dialog.Dialog;
|
||||||
|
import io.xpipe.core.dialog.QueryConverter;
|
||||||
|
import io.xpipe.core.store.DataStore;
|
||||||
|
import io.xpipe.core.store.LocalStore;
|
||||||
|
import io.xpipe.core.store.MachineFileStore;
|
||||||
|
import io.xpipe.core.store.ShellStore;
|
||||||
|
import io.xpipe.core.util.Secret;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
public class DialogHelper {
|
||||||
|
|
||||||
|
@Value
|
||||||
|
public static class Address {
|
||||||
|
String hostname;
|
||||||
|
Integer port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dialog addressQuery(Address address) {
|
||||||
|
var hostNameQuery = Dialog.query("Hostname", false, true, false, address.getHostname(), QueryConverter.STRING);
|
||||||
|
var portQuery = Dialog.query("Port", false, true, false, address.getPort(), QueryConverter.INTEGER);
|
||||||
|
return Dialog.chain(hostNameQuery, portQuery).evaluateTo(() -> new Address(hostNameQuery.getResult(), portQuery.getResult()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dialog machineQuery(DataStore store) {
|
||||||
|
var storeName = XPipeDaemon.getInstance().getStoreName(store).orElse("local");
|
||||||
|
return Dialog.query("Machine", false, true, false, storeName, QueryConverter.STRING).map((String name) -> {
|
||||||
|
if (name.equals("local")) {
|
||||||
|
return new LocalStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
var stored = XPipeDaemon.getInstance().getNamedStore(name);
|
||||||
|
if (stored.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException(String.format("Store not found: %s", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(stored.get() instanceof MachineFileStore)) {
|
||||||
|
throw new IllegalArgumentException(String.format("Store not a machine store: %s", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return stored.get();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dialog shellQuery(DataStore store) {
|
||||||
|
var storeName = XPipeDaemon.getInstance().getStoreName(store).orElse("local");
|
||||||
|
return Dialog.query("Shell", false, true, false, storeName, QueryConverter.STRING).map((String name) -> {
|
||||||
|
if (name.equals("local")) {
|
||||||
|
return new LocalStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
var stored = XPipeDaemon.getInstance().getNamedStore(name);
|
||||||
|
if (stored.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException(String.format("Store not found: %s", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(stored.get() instanceof ShellStore)) {
|
||||||
|
throw new IllegalArgumentException(String.format("Store not a shell store: %s", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return stored.get();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dialog fileQuery(String name) {
|
||||||
|
return Dialog.query("File", true, true, false, name, QueryConverter.STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dialog userQuery(String name) {
|
||||||
|
return Dialog.query("User", false, true, false, name, QueryConverter.STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Dialog passwordQuery(Secret password) {
|
||||||
|
return Dialog.querySecret("Password", false, true, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dialog timeoutQuery(Integer timeout) {
|
||||||
|
return Dialog.query("Timeout", false, true, false, timeout, QueryConverter.INTEGER);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
17
extension/src/main/java/io/xpipe/extension/XPipeDaemon.java
Normal file
17
extension/src/main/java/io/xpipe/extension/XPipeDaemon.java
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package io.xpipe.extension;
|
||||||
|
|
||||||
|
import io.xpipe.core.store.DataStore;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
public interface XPipeDaemon {
|
||||||
|
|
||||||
|
static XPipeDaemon getInstance() {
|
||||||
|
return ServiceLoader.load(XPipeDaemon.class).findFirst().orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<DataStore> getNamedStore(String name);
|
||||||
|
|
||||||
|
Optional<String> getStoreName(DataStore store);
|
||||||
|
}
|
|
@ -201,14 +201,7 @@ public class DynamicOptionsBuilder<T> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V extends T> Comp<?> buildComp() {
|
public final <V extends T> DynamicOptionsBuilder<T> bindChoice(Supplier<Property<? extends V>> creator, Property<T> toSet) {
|
||||||
if (title != null) {
|
|
||||||
entries.add(0, new DynamicOptionsComp.Entry(null, Comp.of(() -> new Label(title.getValue())).styleClass("title")));
|
|
||||||
}
|
|
||||||
return new DynamicOptionsComp(entries, wrap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V extends T> Comp<?> buildBindingComp(Supplier<Property<? extends V>> creator, Property<T> toSet) {
|
|
||||||
props.forEach(prop -> {
|
props.forEach(prop -> {
|
||||||
prop.addListener((c,o,n) -> {
|
prop.addListener((c,o,n) -> {
|
||||||
toSet.unbind();
|
toSet.unbind();
|
||||||
|
@ -216,12 +209,17 @@ public class DynamicOptionsBuilder<T> {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
toSet.bind(creator.get());
|
toSet.bind(creator.get());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comp<?> buildComp() {
|
||||||
if (title != null) {
|
if (title != null) {
|
||||||
entries.add(0, new DynamicOptionsComp.Entry(null, Comp.of(() -> new Label(title.getValue())).styleClass("title")));
|
entries.add(0, new DynamicOptionsComp.Entry(null, Comp.of(() -> new Label(title.getValue())).styleClass("title")));
|
||||||
}
|
}
|
||||||
return new DynamicOptionsComp(entries, wrap);
|
return new DynamicOptionsComp(entries, wrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public <V extends T> Region build() {
|
public <V extends T> Region build() {
|
||||||
return buildComp().createRegion();
|
return buildComp().createRegion();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,4 +36,5 @@ module io.xpipe.extension {
|
||||||
uses io.xpipe.extension.event.EventHandler;
|
uses io.xpipe.extension.event.EventHandler;
|
||||||
uses io.xpipe.extension.prefs.PrefsProvider;
|
uses io.xpipe.extension.prefs.PrefsProvider;
|
||||||
uses io.xpipe.extension.DataStoreProvider;
|
uses io.xpipe.extension.DataStoreProvider;
|
||||||
|
uses io.xpipe.extension.XPipeDaemon;
|
||||||
}
|
}
|
Loading…
Reference in a new issue