Add presence server skeleton
This commit is contained in:
parent
1cf3f738cb
commit
20e341c190
10 changed files with 298 additions and 56 deletions
|
@ -1,3 +1,7 @@
|
||||||
{
|
{
|
||||||
"serveur" :"test"
|
"serveur": {
|
||||||
|
"actif": 1,
|
||||||
|
"uri": "test",
|
||||||
|
"type": "INSA"
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -28,8 +28,7 @@ public class MainApp extends Application {
|
||||||
final Parent content = mainLoader.load();
|
final Parent content = mainLoader.load();
|
||||||
MainController mainController = mainLoader.getController();
|
MainController mainController = mainLoader.getController();
|
||||||
|
|
||||||
userList = new UserList();
|
userList = mainController.getUserList();
|
||||||
mainController.setUserList(userList);
|
|
||||||
|
|
||||||
Scene scene = new Scene(content);
|
Scene scene = new Scene(content);
|
||||||
|
|
||||||
|
@ -44,7 +43,9 @@ public class MainApp extends Application {
|
||||||
@Override
|
@Override
|
||||||
public void stop() throws Exception {
|
public void stop() throws Exception {
|
||||||
// Stop all threads and active connections before exiting
|
// Stop all threads and active connections before exiting
|
||||||
userList.destroy();
|
if (userList != null) {
|
||||||
|
userList.destroy();
|
||||||
|
}
|
||||||
super.stop();
|
super.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
124
src/main/java/fr/insa/clavardator/config/Config.java
Normal file
124
src/main/java/fr/insa/clavardator/config/Config.java
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
package fr.insa.clavardator.config;
|
||||||
|
|
||||||
|
import fr.insa.clavardator.server.PresenceType;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
@SuppressWarnings("FieldCanBeLocal")
|
||||||
|
public class Config {
|
||||||
|
|
||||||
|
private ServerConfig serverConfig;
|
||||||
|
private final String SERVER_KEY = "serveur";
|
||||||
|
|
||||||
|
public Config() {
|
||||||
|
serverConfig = new ServerConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Config(JSONObject obj) {
|
||||||
|
this();
|
||||||
|
if (obj.has(SERVER_KEY)) {
|
||||||
|
this.serverConfig = new ServerConfig(obj.getJSONObject(SERVER_KEY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerConfig getServerConfig() {
|
||||||
|
return serverConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("FieldCanBeLocal")
|
||||||
|
public static class ServerConfig {
|
||||||
|
|
||||||
|
private JSONObject obj;
|
||||||
|
|
||||||
|
private boolean enabled;
|
||||||
|
private String uri;
|
||||||
|
private PresenceType type;
|
||||||
|
|
||||||
|
private final String ENABLED_KEY = "actif";
|
||||||
|
private final String URI_KEY = "uri";
|
||||||
|
private final String TYPE_KEY = "type";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic constructor setting the default server configuration
|
||||||
|
*/
|
||||||
|
public ServerConfig() {
|
||||||
|
enabled = false;
|
||||||
|
uri = "";
|
||||||
|
type = PresenceType.INSA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to read the given JSON object to extract custom user configuration
|
||||||
|
*
|
||||||
|
* @param obj THe JSON object to read config from
|
||||||
|
*/
|
||||||
|
public ServerConfig(JSONObject obj) {
|
||||||
|
this();
|
||||||
|
this.obj = obj;
|
||||||
|
readServerEnabled();
|
||||||
|
if (enabled) {
|
||||||
|
readServerUri();
|
||||||
|
if (uri.isBlank()) {
|
||||||
|
enabled = false;
|
||||||
|
} else {
|
||||||
|
readServerType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads if the server is enabled.
|
||||||
|
* Uses false by default.
|
||||||
|
*/
|
||||||
|
private void readServerEnabled() {
|
||||||
|
try {
|
||||||
|
enabled = obj.getInt(ENABLED_KEY) == 1;
|
||||||
|
} catch (JSONException e) {
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the server URI.
|
||||||
|
* Uses the empty string as default
|
||||||
|
*/
|
||||||
|
private void readServerUri() {
|
||||||
|
try {
|
||||||
|
uri = obj.getString(URI_KEY);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
uri = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the server type.
|
||||||
|
* Uses INSA as default.
|
||||||
|
*/
|
||||||
|
private void readServerType() {
|
||||||
|
try {
|
||||||
|
type = obj.getEnum(PresenceType.class, TYPE_KEY);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
type = PresenceType.INSA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the presence server is enabled.
|
||||||
|
* If this returns false, all other data returned by this object can be ignored.
|
||||||
|
*
|
||||||
|
* @return True if enabled, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PresenceType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package fr.insa.clavardator.util;
|
package fr.insa.clavardator.config;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import fr.insa.clavardator.util.Log;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.json.JSONTokener;
|
import org.json.JSONTokener;
|
||||||
|
@ -34,25 +34,4 @@ public class ConfigLoader {
|
||||||
void onLoaded(Config config);
|
void onLoaded(Config config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Config {
|
|
||||||
@Nullable
|
|
||||||
private String serverUri;
|
|
||||||
private final String SERVER_URI_KEY = "serveur";
|
|
||||||
|
|
||||||
public Config() {
|
|
||||||
serverUri = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Config(JSONObject obj) {
|
|
||||||
this();
|
|
||||||
if (obj.has(SERVER_URI_KEY)) {
|
|
||||||
serverUri = obj.getString(SERVER_URI_KEY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable String getServerUri() {
|
|
||||||
return serverUri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
38
src/main/java/fr/insa/clavardator/server/InsaPresence.java
Normal file
38
src/main/java/fr/insa/clavardator/server/InsaPresence.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package fr.insa.clavardator.server;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class InsaPresence implements Presence {
|
||||||
|
|
||||||
|
private final String path;
|
||||||
|
|
||||||
|
public InsaPresence(String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<String> subscribe() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publish(boolean connected) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptNotifications() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopNotifications() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InetAddress getInetAddress() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
41
src/main/java/fr/insa/clavardator/server/Presence.java
Normal file
41
src/main/java/fr/insa/clavardator/server/Presence.java
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package fr.insa.clavardator.server;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public interface Presence {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribes to this presence server notifications.
|
||||||
|
* A list of Ids representing the current active users is returned.
|
||||||
|
*
|
||||||
|
* @return The list of connected user's Ids
|
||||||
|
*/
|
||||||
|
ArrayList<String> subscribe();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the current user state on the server.
|
||||||
|
* This function must be called on app exit,
|
||||||
|
* or the server won't know this user is inactive.
|
||||||
|
*
|
||||||
|
* @param connected The new user state
|
||||||
|
*/
|
||||||
|
void publish(boolean connected);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts listening to presence server update notifications.
|
||||||
|
*/
|
||||||
|
void acceptNotifications();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops listening to presence server update notifications.
|
||||||
|
*/
|
||||||
|
void stopNotifications();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the presence server InetAddress
|
||||||
|
*
|
||||||
|
* @return The server address
|
||||||
|
*/
|
||||||
|
InetAddress getInetAddress();
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package fr.insa.clavardator.server;
|
||||||
|
|
||||||
|
public class PresenceFactory {
|
||||||
|
public static Presence create(PresenceType type, String uri) throws UnknownPresenceException {
|
||||||
|
switch (type) {
|
||||||
|
case INSA:
|
||||||
|
return new InsaPresence(uri);
|
||||||
|
default:
|
||||||
|
throw new UnknownPresenceException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package fr.insa.clavardator.server;
|
||||||
|
|
||||||
|
public enum PresenceType {
|
||||||
|
INSA,
|
||||||
|
TEST,
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package fr.insa.clavardator.server;
|
||||||
|
|
||||||
|
public class UnknownPresenceException extends Exception {
|
||||||
|
public UnknownPresenceException() {
|
||||||
|
super("Unknown presence server sepcified");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
package fr.insa.clavardator.ui;
|
package fr.insa.clavardator.ui;
|
||||||
|
|
||||||
import com.jfoenix.controls.JFXSnackbar;
|
import com.jfoenix.controls.JFXSnackbar;
|
||||||
|
import fr.insa.clavardator.config.Config;
|
||||||
import fr.insa.clavardator.db.DatabaseController;
|
import fr.insa.clavardator.db.DatabaseController;
|
||||||
|
import fr.insa.clavardator.server.Presence;
|
||||||
|
import fr.insa.clavardator.server.PresenceFactory;
|
||||||
|
import fr.insa.clavardator.server.PresenceType;
|
||||||
|
import fr.insa.clavardator.server.UnknownPresenceException;
|
||||||
import fr.insa.clavardator.ui.chat.ChatController;
|
import fr.insa.clavardator.ui.chat.ChatController;
|
||||||
import fr.insa.clavardator.ui.dialogs.AboutDialogController;
|
import fr.insa.clavardator.ui.dialogs.AboutDialogController;
|
||||||
import fr.insa.clavardator.ui.dialogs.EditUsernameDialogController;
|
import fr.insa.clavardator.ui.dialogs.EditUsernameDialogController;
|
||||||
|
@ -9,7 +14,7 @@ import fr.insa.clavardator.ui.dialogs.SnackbarController;
|
||||||
import fr.insa.clavardator.ui.users.UserListController;
|
import fr.insa.clavardator.ui.users.UserListController;
|
||||||
import fr.insa.clavardator.users.CurrentUser;
|
import fr.insa.clavardator.users.CurrentUser;
|
||||||
import fr.insa.clavardator.users.UserList;
|
import fr.insa.clavardator.users.UserList;
|
||||||
import fr.insa.clavardator.util.ConfigLoader;
|
import fr.insa.clavardator.config.ConfigLoader;
|
||||||
import fr.insa.clavardator.util.Log;
|
import fr.insa.clavardator.util.Log;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
@ -47,6 +52,7 @@ public class MainController implements Initializable {
|
||||||
|
|
||||||
private JFXSnackbar snackbar;
|
private JFXSnackbar snackbar;
|
||||||
private UserList userList;
|
private UserList userList;
|
||||||
|
private Presence presenceServer;
|
||||||
private boolean online;
|
private boolean online;
|
||||||
|
|
||||||
public MainController() {
|
public MainController() {
|
||||||
|
@ -92,7 +98,7 @@ public class MainController implements Initializable {
|
||||||
* </li>
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param mode
|
* @param mode The dialog mode
|
||||||
*/
|
*/
|
||||||
private void openEditUsernameDialog(EditUsernameDialogController.Mode mode) {
|
private void openEditUsernameDialog(EditUsernameDialogController.Mode mode) {
|
||||||
final boolean initialMode = mode == EditUsernameDialogController.Mode.INITIAL;
|
final boolean initialMode = mode == EditUsernameDialogController.Mode.INITIAL;
|
||||||
|
@ -233,36 +239,19 @@ public class MainController implements Initializable {
|
||||||
errorController.show();
|
errorController.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize(URL url, ResourceBundle rb) {
|
|
||||||
loadingController.show("Initialisation de Clavardator...");
|
|
||||||
snackbar = new JFXSnackbar(root);
|
|
||||||
|
|
||||||
listController.setUserSelectedListener((user) -> chatController.setRemoteUser(user));
|
|
||||||
// chatController.setAttachmentListener(() -> System.out.println("attach event"));
|
|
||||||
chatController.setSendErrorListener((e) -> showSnackbarEvent("Erreur: Message non envoyé", SnackbarController.Mode.ERROR));
|
|
||||||
toolbarController.setEditListener(() -> openEditUsernameDialog(EditUsernameDialogController.Mode.EDIT));
|
|
||||||
toolbarController.setAboutListener(this::openAboutDialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onInitError(Exception e) {
|
private void onInitError(Exception e) {
|
||||||
Log.e("INIT", "Error during initialization", e);
|
Log.e("INIT", "Error during initialization", e);
|
||||||
showError();
|
showError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates database if needed, then init current user, and finally load user list
|
* Reads user config, then creates database if needed,
|
||||||
|
* then init current user, and finally load user list.
|
||||||
*/
|
*/
|
||||||
private void initBackend() {
|
private void initBackend() {
|
||||||
ConfigLoader.load((ConfigLoader.Config config) -> {
|
ConfigLoader.load((Config config) -> {
|
||||||
final String serverUri = config.getServerUri();
|
initPresenceServer(config);
|
||||||
if (serverUri != null) {
|
new DatabaseController().initTables(
|
||||||
Log.v("INIT", "Found server URI: " + serverUri);
|
|
||||||
} else {
|
|
||||||
Log.v("INIT", "Server URI not found. Proceeding without");
|
|
||||||
}
|
|
||||||
final DatabaseController db = new DatabaseController();
|
|
||||||
db.initTables(
|
|
||||||
() -> userList.retrievedPreviousUsers(
|
() -> userList.retrievedPreviousUsers(
|
||||||
() -> currentUser.init(this::onInitError),
|
() -> currentUser.init(this::onInitError),
|
||||||
this::onInitError
|
this::onInitError
|
||||||
|
@ -271,16 +260,57 @@ public class MainController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the user list to use.
|
* Initializes the presence server based on user config
|
||||||
* We must set it from the MainApp to allow destroying it on exit.
|
|
||||||
*
|
*
|
||||||
* @param userList The user list to use
|
* @param config The user config
|
||||||
*/
|
*/
|
||||||
public void setUserList(UserList userList) {
|
private void initPresenceServer(Config config) {
|
||||||
this.userList = userList;
|
final Config.ServerConfig serverConfig = config.getServerConfig();
|
||||||
|
if (serverConfig.isEnabled()) {
|
||||||
|
try {
|
||||||
|
final PresenceType type = serverConfig.getType();
|
||||||
|
final String uri = serverConfig.getUri();
|
||||||
|
presenceServer = PresenceFactory.create(type, uri);
|
||||||
|
Log.v("INIT", "Presence server support enabled: " + type + " @ " + uri);
|
||||||
|
} catch (UnknownPresenceException e) {
|
||||||
|
Log.e("INIT", "Presence server type not found", e);
|
||||||
|
presenceServer = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.v("INIT", "Presence server support disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current user list.
|
||||||
|
*
|
||||||
|
* @implNote BE SURE TO CALL .destroy() BEFORE EXITING THE APP.
|
||||||
|
*
|
||||||
|
* @return The current user list
|
||||||
|
*/
|
||||||
|
public UserList getUserList() {
|
||||||
|
return userList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL url, ResourceBundle rb) {
|
||||||
|
loadingController.show("Initialisation de Clavardator...");
|
||||||
|
snackbar = new JFXSnackbar(root);
|
||||||
|
userList = new UserList();
|
||||||
|
|
||||||
|
|
||||||
listController.setUserList(userList);
|
listController.setUserList(userList);
|
||||||
listController.setRefreshUserListener(this::discoverActiveUsers);
|
listController.setRefreshUserListener(this::discoverActiveUsers);
|
||||||
|
listController.setUserSelectedListener((user) -> chatController.setRemoteUser(user));
|
||||||
|
|
||||||
|
chatController.setSendErrorListener((e) -> showSnackbarEvent("Erreur: Message non envoyé", SnackbarController.Mode.ERROR));
|
||||||
|
|
||||||
|
toolbarController.setEditListener(() -> openEditUsernameDialog(EditUsernameDialogController.Mode.EDIT));
|
||||||
|
toolbarController.setAboutListener(this::openAboutDialog);
|
||||||
|
|
||||||
editUserDialogController.setUserList(userList);
|
editUserDialogController.setUserList(userList);
|
||||||
|
|
||||||
initBackend();
|
initBackend();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue