Merge pull request 'Remove TransientLocalDB and no-db Config Value' (#24) from remove-transient-localdb into develop

Reviewed-on: https://git.kske.dev/zdm/envoy/pulls/24
Reviewed-by: delvh <leon@kske.dev>
This commit is contained in:
Kai S. K. Engelbart 2020-09-16 15:48:49 +02:00
commit 8a01229855
5 changed files with 74 additions and 146 deletions

View File

@ -35,7 +35,6 @@ public final class ClientConfig extends Config {
put("server", "s", identity()); put("server", "s", identity());
put("port", "p", Integer::parseInt); put("port", "p", Integer::parseInt);
put("localDB", "db", File::new); put("localDB", "db", File::new);
put("ignoreLocalDB", "nodb", Boolean::parseBoolean);
put("user", "u", identity()); put("user", "u", identity());
put("password", "pw", identity()); put("password", "pw", identity());
} }
@ -58,12 +57,6 @@ public final class ClientConfig extends Config {
*/ */
public File getLocalDB() { return (File) items.get("localDB").get(); } public File getLocalDB() { return (File) items.get("localDB").get(); }
/**
* @return {@code true} if the local database is to be ignored
* @since Envoy Client v0.3-alpha
*/
public Boolean isIgnoreLocalDB() { return (Boolean) items.get("ignoreLocalDB").get(); }
/** /**
* @return the user name * @return the user name
* @since Envoy Client v0.3-alpha * @since Envoy Client v0.3-alpha

View File

@ -1,17 +1,19 @@
package envoy.client.data; package envoy.client.data;
import java.io.*;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.*;
import envoy.data.*; import envoy.data.*;
import envoy.event.GroupResize; import envoy.event.*;
import envoy.event.MessageStatusChange; import envoy.util.SerializationUtils;
import envoy.event.NameChange;
/** /**
* Stores information about the current {@link User} and their {@link Chat}s. * Stores information about the current {@link User} and their {@link Chat}s.
* For message ID generation a {@link IDGenerator} is stored as well. * For message ID generation a {@link IDGenerator} is stored as well.
* <p> * <p>
* The managed objects are stored inside a folder in the local file system.
* <p>
* Project: <strong>envoy-client</strong><br> * Project: <strong>envoy-client</strong><br>
* File: <strong>LocalDB.java</strong><br> * File: <strong>LocalDB.java</strong><br>
* Created: <strong>3 Feb 2020</strong><br> * Created: <strong>3 Feb 2020</strong><br>
@ -19,60 +21,105 @@ import envoy.event.NameChange;
* @author Kai S. K. Engelbart * @author Kai S. K. Engelbart
* @since Envoy Client v0.3-alpha * @since Envoy Client v0.3-alpha
*/ */
public abstract class LocalDB { public final class LocalDB {
protected User user; private User user;
protected Map<String, User> users = new HashMap<>(); private Map<String, User> users = new HashMap<>();
protected List<Chat> chats = new ArrayList<>(); private List<Chat> chats = new ArrayList<>();
protected IDGenerator idGenerator; private IDGenerator idGenerator;
protected CacheMap cacheMap = new CacheMap(); private CacheMap cacheMap = new CacheMap();
protected Instant lastSync = Instant.EPOCH; private Instant lastSync = Instant.EPOCH;
private File dbDir, userFile, idGeneratorFile, usersFile;
{ /**
* Constructs an empty local database. To serialize any user-specific data to
* the file system, call {@link LocalDB#initializeUserStorage()} first
* and then {@link LocalDB#save(boolean)}.
*
* @param dbDir the directory in which to persist data
* @throws IOException if {@code dbDir} is a file (and not a directory)
* @since Envoy Client v0.2-beta
*/
public LocalDB(File dbDir) throws IOException {
this.dbDir = dbDir;
// Test if the database directory is actually a directory
if (dbDir.exists() && !dbDir.isDirectory())
throw new IOException(String.format("LocalDBDir '%s' is not a directory!", dbDir.getAbsolutePath()));
// Initialize global files
idGeneratorFile = new File(dbDir, "id_gen.db");
usersFile = new File(dbDir, "users.db");
// Initialize offline caches
cacheMap.put(Message.class, new Cache<>()); cacheMap.put(Message.class, new Cache<>());
cacheMap.put(MessageStatusChange.class, new Cache<>()); cacheMap.put(MessageStatusChange.class, new Cache<>());
} }
/** /**
* Initializes a storage space for a user-specific list of chats. * Creates a database file for a user-specific list of chats.
* *
* @since Envoy Client v0.3-alpha * @throws IllegalStateException if the client user is not specified
* @since Envoy Client v0.1-alpha
*/ */
public void initializeUserStorage() {} public void initializeUserStorage() {
if (user == null) throw new IllegalStateException("Client user is null, cannot initialize user storage");
userFile = new File(dbDir, user.getID() + ".db");
}
/** /**
* Stores all users. If the client user is specified, their chats will be stored * Stores all users. If the client user is specified, their chats will be stored
* as well. The message id generator will also be saved if present. * as well. The message id generator will also be saved if present.
* *
* @param isOnline determines which {@code lastSync} time stamp is saved * @param isOnline determines which {@code lastSync} time stamp is saved
* @throws Exception if the saving process failed * @throws IOException if the saving process failed
* @since Envoy Client v0.3-alpha * @since Envoy Client v0.3-alpha
*/ */
public void save(boolean isOnline) throws Exception {} public void save(boolean isOnline) throws IOException {
// Save users
SerializationUtils.write(usersFile, users);
// Save user data and last sync time stamp
if (user != null) SerializationUtils.write(userFile, chats, cacheMap, isOnline ? Instant.now() : lastSync);
// Save id generator
if (hasIDGenerator()) SerializationUtils.write(idGeneratorFile, idGenerator);
}
/** /**
* Loads all user data. * Loads all user data.
* *
* @throws Exception if the loading process failed * @throws ClassNotFoundException if the loading process failed
* @throws IOException if the loading process failed
* @since Envoy Client v0.3-alpha * @since Envoy Client v0.3-alpha
*/ */
public void loadUsers() throws Exception {} public void loadUsers() throws ClassNotFoundException, IOException { users = SerializationUtils.read(usersFile, HashMap.class); }
/** /**
* Loads all data of the client user. * Loads all data of the client user.
* *
* @throws Exception if the loading process failed * @throws ClassNotFoundException if the loading process failed
* @throws IOException if the loading process failed
* @since Envoy Client v0.3-alpha * @since Envoy Client v0.3-alpha
*/ */
public void loadUserData() throws Exception {} public void loadUserData() throws ClassNotFoundException, IOException {
try (var in = new ObjectInputStream(new FileInputStream(userFile))) {
chats = (ArrayList<Chat>) in.readObject();
cacheMap = (CacheMap) in.readObject();
lastSync = (Instant) in.readObject();
}
}
/** /**
* Loads the ID generator. Any exception thrown during this process is ignored. * Loads the ID generator. Any exception thrown during this process is ignored.
* *
* @since Envoy Client v0.3-alpha * @since Envoy Client v0.3-alpha
*/ */
public void loadIDGenerator() {} public void loadIDGenerator() {
try {
idGenerator = SerializationUtils.read(idGeneratorFile, IDGenerator.class);
} catch (ClassNotFoundException | IOException e) {}
}
/** /**
* Synchronizes the contact list of the client user with the chat and user * Synchronizes the contact list of the client user with the chat and user
* storage. * storage.

View File

@ -1,90 +0,0 @@
package envoy.client.data;
import java.io.*;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import envoy.data.IDGenerator;
import envoy.util.SerializationUtils;
/**
* Implements a {@link LocalDB} in a way that stores all information inside a
* folder on the local file system.
* <p>
* Project: <strong>envoy-client</strong><br>
* File: <strong>PersistentLocalDB.java</strong><br>
* Created: <strong>27.10.2019</strong><br>
*
* @author Kai S. K. Engelbart
* @author Maximilian K&auml;fer
* @since Envoy Client v0.1-alpha
*/
public final class PersistentLocalDB extends LocalDB {
private File dbDir, userFile, idGeneratorFile, usersFile;
/**
* Constructs an empty local database. To serialize any user-specific data to
* the file system, call {@link PersistentLocalDB#initializeUserStorage()} first
* and then {@link PersistentLocalDB#save(boolean)}.
*
* @param dbDir the directory in which to persist data
* @throws IOException if {@code dbDir} is a file (and not a directory)
* @since Envoy Client v0.1-alpha
*/
public PersistentLocalDB(File dbDir) throws IOException {
this.dbDir = dbDir;
// Test if the database directory is actually a directory
if (dbDir.exists() && !dbDir.isDirectory())
throw new IOException(String.format("LocalDBDir '%s' is not a directory!", dbDir.getAbsolutePath()));
// Initialize global files
idGeneratorFile = new File(dbDir, "id_gen.db");
usersFile = new File(dbDir, "users.db");
}
/**
* Creates a database file for a user-specific list of chats.
*
* @throws IllegalStateException if the client user is not specified
* @since Envoy Client v0.1-alpha
*/
@Override
public void initializeUserStorage() {
if (user == null) throw new IllegalStateException("Client user is null, cannot initialize user storage");
userFile = new File(dbDir, user.getID() + ".db");
}
@Override
public void save(boolean isOnline) throws IOException {
// Save users
SerializationUtils.write(usersFile, users);
// Save user data and last sync time stamp
if (user != null) SerializationUtils.write(userFile, chats, cacheMap, isOnline ? Instant.now() : lastSync);
// Save id generator
if (hasIDGenerator()) SerializationUtils.write(idGeneratorFile, idGenerator);
}
@Override
public void loadUsers() throws ClassNotFoundException, IOException { users = SerializationUtils.read(usersFile, HashMap.class); }
@Override
public void loadUserData() throws ClassNotFoundException, IOException {
try (var in = new ObjectInputStream(new FileInputStream(userFile))) {
chats = (ArrayList<Chat>) in.readObject();
cacheMap = (CacheMap) in.readObject();
lastSync = (Instant) in.readObject();
}
}
@Override
public void loadIDGenerator() {
try {
idGenerator = SerializationUtils.read(idGeneratorFile, IDGenerator.class);
} catch (ClassNotFoundException | IOException e) {}
}
}

View File

@ -1,15 +0,0 @@
package envoy.client.data;
/**
* Implements a {@link LocalDB} in a way that does not persist any information
* after application shutdown.
* <p>
* Project: <strong>envoy-client</strong><br>
* File: <strong>TransientLocalDB.java</strong><br>
* Created: <strong>3 Feb 2020</strong><br>
*
* @author Kai S. K. Engelbart
* @since Envoy Client v0.3-alpha
*/
public final class TransientLocalDB extends LocalDB {
}

View File

@ -1,12 +1,9 @@
package envoy.client.ui; package envoy.client.ui;
import java.io.File; import java.io.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.time.Instant; import java.time.Instant;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.logging.Level; import java.util.logging.*;
import java.util.logging.Logger;
import javafx.application.Application; import javafx.application.Application;
import javafx.scene.control.Alert; import javafx.scene.control.Alert;
@ -19,8 +16,7 @@ import envoy.client.ui.SceneContext.SceneInfo;
import envoy.client.ui.controller.LoginScene; import envoy.client.ui.controller.LoginScene;
import envoy.data.*; import envoy.data.*;
import envoy.data.User.UserStatus; import envoy.data.User.UserStatus;
import envoy.event.GroupMessageStatusChange; import envoy.event.*;
import envoy.event.MessageStatusChange;
import envoy.exception.EnvoyException; import envoy.exception.EnvoyException;
import envoy.util.EnvoyLog; import envoy.util.EnvoyLog;
@ -70,11 +66,8 @@ public final class Startup extends Application {
logger.log(Level.INFO, "Envoy starting..."); logger.log(Level.INFO, "Envoy starting...");
// Initialize the local database // Initialize the local database
if (config.isIgnoreLocalDB()) { try {
localDB = new TransientLocalDB(); localDB = new LocalDB(new File(config.getHomeDirectory(), config.getLocalDB().getPath()));
new Alert(AlertType.WARNING, "Ignoring local database.\nMessages will not be saved!").showAndWait();
} else try {
localDB = new PersistentLocalDB(new File(config.getHomeDirectory(), config.getLocalDB().getPath()));
} catch (final IOException e3) { } catch (final IOException e3) {
logger.log(Level.SEVERE, "Could not initialize local database: ", e3); logger.log(Level.SEVERE, "Could not initialize local database: ", e3);
new Alert(AlertType.ERROR, "Could not initialize local database!\n" + e3).showAndWait(); new Alert(AlertType.ERROR, "Could not initialize local database!\n" + e3).showAndWait();