mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-21 23:20:23 +00:00
More error fixes
This commit is contained in:
parent
32c3f42aaa
commit
50f8e40d99
6 changed files with 45 additions and 102 deletions
|
@ -64,17 +64,11 @@ public class DataStoreProviders {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T extends DataStoreProvider> T byStore(DataStore store) {
|
public static <T extends DataStoreProvider> T byStore(DataStore store) {
|
||||||
return (T) byStoreClass(store.getClass()).orElseThrow();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T extends DataStoreProvider> Optional<T> byStoreClass(Class<?> c) {
|
|
||||||
if (ALL == null) {
|
if (ALL == null) {
|
||||||
throw new IllegalStateException("Not initialized");
|
throw new IllegalStateException("Not initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Optional<T>)
|
return (T) ALL.stream().filter(d -> d.getStoreClasses().contains(store.getClass())).findAny().orElseThrow(() -> new IllegalArgumentException("Unknown store class"));
|
||||||
ALL.stream().filter(d -> d.getStoreClasses().contains(c)).findAny();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<DataStoreProvider> getAll() {
|
public static List<DataStoreProvider> getAll() {
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package io.xpipe.app.storage;
|
|
||||||
|
|
||||||
import io.xpipe.app.issue.ErrorEvent;
|
|
||||||
import io.xpipe.core.store.DataStore;
|
|
||||||
import io.xpipe.core.util.JacksonMapper;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
|
|
||||||
public class DataStorageParser {
|
|
||||||
|
|
||||||
public static DataStore storeFromNode(JsonNode node) {
|
|
||||||
var mapper = JacksonMapper.getDefault();
|
|
||||||
try {
|
|
||||||
return mapper.treeToValue(node, DataStore.class);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
ErrorEvent.fromThrowable(e).handle();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
package io.xpipe.app.storage;
|
|
||||||
|
|
||||||
import io.xpipe.core.store.DataStore;
|
|
||||||
import io.xpipe.core.util.JacksonMapper;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
|
|
||||||
public class DataStorageWriter {
|
|
||||||
|
|
||||||
public static JsonNode storeToNode(DataStore store) {
|
|
||||||
var mapper = JacksonMapper.getDefault();
|
|
||||||
return mapper.valueToTree(store);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -82,6 +82,7 @@ public class DataStoreEntry extends StorageElement {
|
||||||
String name,
|
String name,
|
||||||
Instant lastUsed,
|
Instant lastUsed,
|
||||||
Instant lastModified,
|
Instant lastModified,
|
||||||
|
DataStore store,
|
||||||
JsonNode storeNode,
|
JsonNode storeNode,
|
||||||
boolean dirty,
|
boolean dirty,
|
||||||
Validity validity,
|
Validity validity,
|
||||||
|
@ -93,7 +94,7 @@ public class DataStoreEntry extends StorageElement {
|
||||||
Order explicitOrder) {
|
Order explicitOrder) {
|
||||||
super(directory, uuid, name, lastUsed, lastModified, dirty);
|
super(directory, uuid, name, lastUsed, lastModified, dirty);
|
||||||
this.categoryUuid = categoryUuid;
|
this.categoryUuid = categoryUuid;
|
||||||
this.store = DataStorageParser.storeFromNode(storeNode);
|
this.store = store;
|
||||||
this.storeNode = storeNode;
|
this.storeNode = storeNode;
|
||||||
this.validity = validity;
|
this.validity = validity;
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
|
@ -101,7 +102,7 @@ public class DataStoreEntry extends StorageElement {
|
||||||
this.color = color;
|
this.color = color;
|
||||||
this.explicitOrder = explicitOrder;
|
this.explicitOrder = explicitOrder;
|
||||||
this.provider = store != null
|
this.provider = store != null
|
||||||
? DataStoreProviders.byStoreClass(store.getClass()).orElse(null)
|
? DataStoreProviders.byStore(store)
|
||||||
: null;
|
: null;
|
||||||
this.storePersistentStateNode = storePersistentState;
|
this.storePersistentStateNode = storePersistentState;
|
||||||
this.notes = notes;
|
this.notes = notes;
|
||||||
|
@ -149,8 +150,9 @@ public class DataStoreEntry extends StorageElement {
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static DataStoreEntry createNew(
|
public static DataStoreEntry createNew(
|
||||||
@NonNull UUID uuid, @NonNull UUID categoryUuid, @NonNull String name, @NonNull DataStore store) {
|
@NonNull UUID uuid, @NonNull UUID categoryUuid, @NonNull String name, @NonNull DataStore store) {
|
||||||
var node = DataStorageWriter.storeToNode(store);
|
var node = JacksonMapper.getDefault().valueToTree(store);
|
||||||
var validity = DataStorageParser.storeFromNode(node) == null
|
var storeFromNode = JacksonMapper.getDefault().treeToValue(node, DataStore.class);
|
||||||
|
var validity = storeFromNode == null
|
||||||
? Validity.LOAD_FAILED
|
? Validity.LOAD_FAILED
|
||||||
: store.isComplete() ? Validity.COMPLETE : Validity.INCOMPLETE;
|
: store.isComplete() ? Validity.COMPLETE : Validity.INCOMPLETE;
|
||||||
var entry = new DataStoreEntry(
|
var entry = new DataStoreEntry(
|
||||||
|
@ -160,6 +162,7 @@ public class DataStoreEntry extends StorageElement {
|
||||||
name,
|
name,
|
||||||
Instant.now(),
|
Instant.now(),
|
||||||
Instant.now(),
|
Instant.now(),
|
||||||
|
storeFromNode,
|
||||||
node,
|
node,
|
||||||
true,
|
true,
|
||||||
validity,
|
validity,
|
||||||
|
@ -172,39 +175,6 @@ public class DataStoreEntry extends StorageElement {
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private static DataStoreEntry createExisting(
|
|
||||||
@NonNull Path directory,
|
|
||||||
@NonNull UUID uuid,
|
|
||||||
@NonNull UUID categoryUuid,
|
|
||||||
@NonNull String name,
|
|
||||||
@NonNull Instant lastUsed,
|
|
||||||
@NonNull Instant lastModified,
|
|
||||||
JsonNode storeNode,
|
|
||||||
Configuration configuration,
|
|
||||||
JsonNode storePersistentState,
|
|
||||||
boolean expanded,
|
|
||||||
DataStoreColor color,
|
|
||||||
String notes,
|
|
||||||
Order order) {
|
|
||||||
return new DataStoreEntry(
|
|
||||||
directory,
|
|
||||||
uuid,
|
|
||||||
categoryUuid,
|
|
||||||
name,
|
|
||||||
lastUsed,
|
|
||||||
lastModified,
|
|
||||||
storeNode,
|
|
||||||
false,
|
|
||||||
Validity.INCOMPLETE,
|
|
||||||
configuration,
|
|
||||||
storePersistentState,
|
|
||||||
expanded,
|
|
||||||
color,
|
|
||||||
notes,
|
|
||||||
order);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Optional<DataStoreEntry> fromDirectory(Path dir) throws Exception {
|
public static Optional<DataStoreEntry> fromDirectory(Path dir) throws Exception {
|
||||||
ObjectMapper mapper = JacksonMapper.getDefault();
|
ObjectMapper mapper = JacksonMapper.getDefault();
|
||||||
|
|
||||||
|
@ -277,20 +247,19 @@ public class DataStoreEntry extends StorageElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store loading is prone to errors.
|
// Store loading is prone to errors.
|
||||||
JsonNode storeNode = null;
|
JsonNode storeNode = DataStorageEncryption.readPossiblyEncryptedNode(mapper.readTree(storeFile.toFile()));
|
||||||
try {
|
var store = JacksonMapper.getDefault().treeToValue(storeNode, DataStore.class);
|
||||||
storeNode = DataStorageEncryption.readPossiblyEncryptedNode(mapper.readTree(storeFile.toFile()));
|
return Optional.of(new DataStoreEntry(
|
||||||
} catch (Exception e) {
|
|
||||||
ErrorEvent.fromThrowable(e).handle();
|
|
||||||
}
|
|
||||||
return Optional.of(createExisting(
|
|
||||||
dir,
|
dir,
|
||||||
uuid,
|
uuid,
|
||||||
categoryUuid,
|
categoryUuid,
|
||||||
name,
|
name,
|
||||||
lastUsed,
|
lastUsed,
|
||||||
lastModified,
|
lastModified,
|
||||||
|
store,
|
||||||
storeNode,
|
storeNode,
|
||||||
|
false,
|
||||||
|
Validity.INCOMPLETE,
|
||||||
configuration,
|
configuration,
|
||||||
persistentState,
|
persistentState,
|
||||||
expanded,
|
expanded,
|
||||||
|
@ -482,7 +451,7 @@ public class DataStoreEntry extends StorageElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.store = store;
|
this.store = store;
|
||||||
this.storeNode = DataStorageWriter.storeToNode(store);
|
this.storeNode = JacksonMapper.getDefault().valueToTree(store);
|
||||||
if (updateTime) {
|
if (updateTime) {
|
||||||
lastModified = Instant.now();
|
lastModified = Instant.now();
|
||||||
}
|
}
|
||||||
|
@ -491,7 +460,7 @@ public class DataStoreEntry extends StorageElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reassignStore() {
|
public void reassignStore() {
|
||||||
this.storeNode = DataStorageWriter.storeToNode(store);
|
this.storeNode = JacksonMapper.getDefault().valueToTree(store);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,7 +497,14 @@ public class DataStoreEntry extends StorageElement {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newStore = DataStorageParser.storeFromNode(storeNode);
|
DataStore newStore;
|
||||||
|
try {
|
||||||
|
newStore = JacksonMapper.getDefault().treeToValue(storeNode, DataStore.class);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
ErrorEvent.fromThrowable(e).handle();
|
||||||
|
newStore = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (newStore == null) {
|
if (newStore == null) {
|
||||||
store = null;
|
store = null;
|
||||||
validity = Validity.LOAD_FAILED;
|
validity = Validity.LOAD_FAILED;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.app.storage;
|
package io.xpipe.app.storage;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JacksonException;
|
||||||
import io.xpipe.app.ext.DataStorageExtensionProvider;
|
import io.xpipe.app.ext.DataStorageExtensionProvider;
|
||||||
import io.xpipe.app.issue.ErrorEvent;
|
import io.xpipe.app.issue.ErrorEvent;
|
||||||
import io.xpipe.app.issue.TrackEvent;
|
import io.xpipe.app.issue.TrackEvent;
|
||||||
|
@ -7,6 +8,7 @@ import io.xpipe.app.prefs.AppPrefs;
|
||||||
import io.xpipe.core.process.OsType;
|
import io.xpipe.core.process.OsType;
|
||||||
import io.xpipe.core.store.LocalStore;
|
import io.xpipe.core.store.LocalStore;
|
||||||
|
|
||||||
|
import io.xpipe.core.util.JacksonMapper;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
|
@ -129,6 +131,16 @@ public class StandardStorage extends DataStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
storeEntries.put(entry.get(), entry.get());
|
storeEntries.put(entry.get(), entry.get());
|
||||||
|
} catch (JacksonException ex) {
|
||||||
|
// Data corruption and schema changes are expected
|
||||||
|
|
||||||
|
// We only keep invalid entries in developer mode as there's no point in keeping them in
|
||||||
|
// production.
|
||||||
|
if (AppPrefs.get().isDevelopmentEnvironment()) {
|
||||||
|
directoriesToKeep.add(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorEvent.fromThrowable(ex).expected().omit().build().handle();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
// IO exceptions are not expected
|
// IO exceptions are not expected
|
||||||
exception.set(new IOException("Unable to load data from " + path + ". Is it corrupted?", ex));
|
exception.set(new IOException("Unable to load data from " + path + ". Is it corrupted?", ex));
|
||||||
|
@ -221,7 +233,7 @@ public class StandardStorage extends DataStorage {
|
||||||
.filter(entry -> entry.getValidity() != DataStoreEntry.Validity.LOAD_FAILED)
|
.filter(entry -> entry.getValidity() != DataStoreEntry.Validity.LOAD_FAILED)
|
||||||
.forEach(entry -> {
|
.forEach(entry -> {
|
||||||
entry.dirty = true;
|
entry.dirty = true;
|
||||||
entry.setStoreNode(DataStorageWriter.storeToNode(entry.getStore()));
|
entry.setStoreNode(JacksonMapper.getDefault().valueToTree(entry.getStore()));
|
||||||
});
|
});
|
||||||
save(false);
|
save(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
package io.xpipe.core.util;
|
package io.xpipe.core.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||||
|
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.databind.*;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.jsontype.NamedType;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import io.xpipe.core.dialog.BaseQueryElement;
|
import io.xpipe.core.dialog.BaseQueryElement;
|
||||||
import io.xpipe.core.dialog.BusyElement;
|
import io.xpipe.core.dialog.BusyElement;
|
||||||
import io.xpipe.core.dialog.ChoiceElement;
|
import io.xpipe.core.dialog.ChoiceElement;
|
||||||
|
@ -11,18 +19,7 @@ import io.xpipe.core.store.FilePath;
|
||||||
import io.xpipe.core.store.LocalStore;
|
import io.xpipe.core.store.LocalStore;
|
||||||
import io.xpipe.core.store.StorePath;
|
import io.xpipe.core.store.StorePath;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
|
||||||
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.databind.*;
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|
||||||
import com.fasterxml.jackson.databind.jsontype.NamedType;
|
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
|
||||||
import com.fasterxml.jackson.databind.type.ArrayType;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.WildcardType;
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -35,8 +32,6 @@ public class CoreJacksonModule extends SimpleModule {
|
||||||
context.registerSubtypes(
|
context.registerSubtypes(
|
||||||
new NamedType(InPlaceSecretValue.class),
|
new NamedType(InPlaceSecretValue.class),
|
||||||
new NamedType(LocalStore.class),
|
new NamedType(LocalStore.class),
|
||||||
new NamedType(ArrayType.class),
|
|
||||||
new NamedType(WildcardType.class),
|
|
||||||
new NamedType(BaseQueryElement.class),
|
new NamedType(BaseQueryElement.class),
|
||||||
new NamedType(ChoiceElement.class),
|
new NamedType(ChoiceElement.class),
|
||||||
new NamedType(BusyElement.class),
|
new NamedType(BusyElement.class),
|
||||||
|
|
Loading…
Reference in a new issue