Add documentation to common package
This commit is contained in:
parent
6e05784eb7
commit
f3813d23e2
12 changed files with 201 additions and 11 deletions
|
@ -3,28 +3,52 @@ package fr.univ.lyon1.common;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base type of chat channel
|
||||||
|
*/
|
||||||
public class Channel implements Serializable {
|
public class Channel implements Serializable {
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an existing channel
|
||||||
|
* @param uuid the channel unique id
|
||||||
|
* @param name the channel name
|
||||||
|
*/
|
||||||
public Channel(UUID uuid, String name) {
|
public Channel(UUID uuid, String name) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new channel
|
||||||
|
* @param name the new channel name
|
||||||
|
*/
|
||||||
public Channel(String name) {
|
public Channel(String name) {
|
||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID();
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channel unique id
|
||||||
|
* @return the channel unique id
|
||||||
|
*/
|
||||||
public UUID getUUID() {
|
public UUID getUUID() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channel name
|
||||||
|
* @return the channel name
|
||||||
|
*/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String version of the channel
|
||||||
|
* @return the channel name
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
|
|
|
@ -10,12 +10,13 @@ import java.io.InputStream;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
keytool -genkeypair -alias server -keyalg EC \
|
* The SSL context for client/server communication
|
||||||
-sigalg SHA384withECDSA -keysize 256 -keystore servercert.p12 \
|
* A key store can be generated with this command:
|
||||||
-storetype pkcs12 -v -storepass abc123 -validity 10000 -ext san=ip:127.0.0.1
|
* keytool -genkeypair -alias server -keyalg EC \
|
||||||
|
* -sigalg SHA384withECDSA -keysize 256 -keystore servercert.p12 \
|
||||||
|
* -storetype pkcs12 -v -storepass abc123 -validity 10000 -ext san=ip:127.0.0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ChatSSL {
|
public class ChatSSL {
|
||||||
public static String trustStoreName = "servercert.p12";
|
public static String trustStoreName = "servercert.p12";
|
||||||
public static String keyStoreName = "servercert.p12";
|
public static String keyStoreName = "servercert.p12";
|
||||||
|
@ -23,25 +24,37 @@ public class ChatSSL {
|
||||||
private static char[] trustStorePassword = "abc123".toCharArray();
|
private static char[] trustStorePassword = "abc123".toCharArray();
|
||||||
private static char[] keyStorePassword = "abc123".toCharArray();
|
private static char[] keyStorePassword = "abc123".toCharArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the SSL context for communication
|
||||||
|
* @return the SSL context
|
||||||
|
*/
|
||||||
public static SSLContext getSSLContext() {
|
public static SSLContext getSSLContext() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Get the SSL trust store from package resources
|
||||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
InputStream tstore = Connection.class
|
InputStream tstore = Connection.class
|
||||||
.getResourceAsStream("/" + trustStoreName);
|
.getResourceAsStream("/" + trustStoreName);
|
||||||
trustStore.load(tstore, trustStorePassword);
|
trustStore.load(tstore, trustStorePassword);
|
||||||
tstore.close();
|
tstore.close();
|
||||||
|
|
||||||
|
// Create a trust factory from the trust store
|
||||||
TrustManagerFactory tmf = TrustManagerFactory
|
TrustManagerFactory tmf = TrustManagerFactory
|
||||||
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||||
tmf.init(trustStore);
|
tmf.init(trustStore);
|
||||||
|
|
||||||
|
// Get the SSL key store from package resources
|
||||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
InputStream kstore = Connection.class
|
InputStream kstore = Connection.class
|
||||||
.getResourceAsStream("/" + keyStoreName);
|
.getResourceAsStream("/" + keyStoreName);
|
||||||
keyStore.load(kstore, keyStorePassword);
|
keyStore.load(kstore, keyStorePassword);
|
||||||
|
kstore.close();
|
||||||
|
|
||||||
|
// Create a key factory from the key store
|
||||||
KeyManagerFactory kmf = KeyManagerFactory
|
KeyManagerFactory kmf = KeyManagerFactory
|
||||||
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||||
kmf.init(keyStore, keyStorePassword);
|
kmf.init(keyStore, keyStorePassword);
|
||||||
|
|
||||||
|
// Generate the SSL context
|
||||||
SSLContext ctx = SSLContext.getInstance("TLS");
|
SSLContext ctx = SSLContext.getInstance("TLS");
|
||||||
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(),
|
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(),
|
||||||
SecureRandom.getInstanceStrong());
|
SecureRandom.getInstanceStrong());
|
||||||
|
|
|
@ -3,13 +3,21 @@ package fr.univ.lyon1.common;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base type of message in client/server communication
|
||||||
|
*/
|
||||||
public class Message implements Serializable {
|
public class Message implements Serializable {
|
||||||
private Channel channel;
|
private Channel channel;
|
||||||
private User sender;
|
private User sender;
|
||||||
private final String content;
|
private final String content;
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message with a specified sender
|
||||||
|
* @param channel the target channel
|
||||||
|
* @param sender the sender
|
||||||
|
* @param content the content
|
||||||
|
*/
|
||||||
public Message(Channel channel, User sender, String content) {
|
public Message(Channel channel, User sender, String content) {
|
||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID();
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
|
@ -17,6 +25,13 @@ public class Message implements Serializable {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an existing message
|
||||||
|
* @param uuid the unique id
|
||||||
|
* @param channel the channel
|
||||||
|
* @param sender the sender
|
||||||
|
* @param content the content
|
||||||
|
*/
|
||||||
public Message(UUID uuid, Channel channel, User sender, String content) {
|
public Message(UUID uuid, Channel channel, User sender, String content) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
|
@ -24,32 +39,64 @@ public class Message implements Serializable {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a nex message without specifying the sender
|
||||||
|
* @param content the content
|
||||||
|
* @param channel the target channel
|
||||||
|
*/
|
||||||
public Message(String content, Channel channel) {
|
public Message(String content, Channel channel) {
|
||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID();
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a reply if this message
|
||||||
|
* This use the same chanel of the original one
|
||||||
|
* @param user the sender
|
||||||
|
* @param content the content
|
||||||
|
* @return the message reply
|
||||||
|
*/
|
||||||
public Message repley(User user, String content) {
|
public Message repley(User user, String content) {
|
||||||
return new Message(this.channel, user, content);
|
return new Message(this.channel, user, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the sender
|
||||||
|
* @param sender the new sender
|
||||||
|
*/
|
||||||
public void setSender(User sender) {
|
public void setSender(User sender) {
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message channel
|
||||||
|
* @return the channel
|
||||||
|
*/
|
||||||
public Channel getChannel() {
|
public Channel getChannel() {
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message sender
|
||||||
|
* @return the sender
|
||||||
|
*/
|
||||||
public User getSender() {
|
public User getSender() {
|
||||||
return sender;
|
return sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the content of the message
|
||||||
|
* @return the message content
|
||||||
|
*/
|
||||||
public String getContent() {
|
public String getContent() {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Printable version of the message
|
||||||
|
* @return the channel, sender and the content
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (channel != null)
|
if (channel != null)
|
||||||
|
|
|
@ -2,19 +2,36 @@ package fr.univ.lyon1.common;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client server configuration
|
||||||
|
* ToDo should be in gui and not in common ?
|
||||||
|
*/
|
||||||
public record ServerConfiguration(@NotNull String address, int port) {
|
public record ServerConfiguration(@NotNull String address, int port) {
|
||||||
@NotNull
|
@NotNull
|
||||||
private static final File file = new File("connection.properties");
|
private static final File file = new File("connection.properties");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a configuration
|
||||||
|
* @param address the server address
|
||||||
|
* @param port the server port
|
||||||
|
*/
|
||||||
public ServerConfiguration(@NotNull String address, int port) {
|
public ServerConfiguration(@NotNull String address, int port) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ServerConfiguration load() throws IOException, NumberFormatException {
|
/**
|
||||||
|
* Load configuration from file
|
||||||
|
* @return the configuration
|
||||||
|
* @throws IOException if the file doesn't exist
|
||||||
|
*/
|
||||||
|
public static ServerConfiguration load() throws IOException {
|
||||||
// Check if file non exists, return error to launch server configuration
|
// Check if file non exists, return error to launch server configuration
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
System.out.println("File not exists");
|
System.out.println("File not exists");
|
||||||
|
@ -26,6 +43,10 @@ public record ServerConfiguration(@NotNull String address, int port) {
|
||||||
return new ServerConfiguration(properties.getProperty("address"), Integer.parseInt(properties.getProperty("port")));
|
return new ServerConfiguration(properties.getProperty("address"), Integer.parseInt(properties.getProperty("port")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save configuration to file
|
||||||
|
* @throws IOException if fail to write the file
|
||||||
|
*/
|
||||||
public void save() throws IOException {
|
public void save() throws IOException {
|
||||||
@NotNull final Properties properties = new Properties();
|
@NotNull final Properties properties = new Properties();
|
||||||
properties.setProperty("address", this.address);
|
properties.setProperty("address", this.address);
|
||||||
|
@ -33,10 +54,18 @@ public record ServerConfiguration(@NotNull String address, int port) {
|
||||||
properties.store(new FileWriter(file), "Information needed to connect to the server");
|
properties.store(new FileWriter(file), "Information needed to connect to the server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the server address
|
||||||
|
* @return the server address
|
||||||
|
*/
|
||||||
public @NotNull String getAddress() {
|
public @NotNull String getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the server port
|
||||||
|
* @return the server port
|
||||||
|
*/
|
||||||
public int getPort() {
|
public int getPort() {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,28 +3,52 @@ package fr.univ.lyon1.common;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base type of user for client/server communication
|
||||||
|
*/
|
||||||
public class User implements Serializable {
|
public class User implements Serializable {
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an existing user
|
||||||
|
* @param uuid the user unique id
|
||||||
|
* @param username the username
|
||||||
|
*/
|
||||||
public User(UUID uuid, String username) {
|
public User(UUID uuid, String username) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new user
|
||||||
|
* @param username the username
|
||||||
|
*/
|
||||||
public User(String username) {
|
public User(String username) {
|
||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID();
|
||||||
this.username = username;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the user unique id
|
||||||
|
* @return thee unique id
|
||||||
|
*/
|
||||||
public UUID getUUID() {
|
public UUID getUUID() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the username
|
||||||
|
* @return the username
|
||||||
|
*/
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user as a string
|
||||||
|
* @return the username
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return username;
|
return username;
|
||||||
|
|
|
@ -4,19 +4,37 @@ import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command is the base object transmitted between clients and server
|
||||||
|
*/
|
||||||
public class Command implements Serializable {
|
public class Command implements Serializable {
|
||||||
private final CommandType type;
|
private final CommandType type;
|
||||||
private final List<Object> args;
|
private final List<Object> args;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class need a type and a list of arguments
|
||||||
|
* @see CommandType
|
||||||
|
* @param type The type of the command
|
||||||
|
* @param args A list of arguments for the given command
|
||||||
|
*/
|
||||||
public Command(CommandType type, List<?> args) {
|
public Command(CommandType type, List<?> args) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.args = (List<Object>) args;
|
this.args = (List<Object>) args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of the command
|
||||||
|
* @see CommandType
|
||||||
|
* @return the command type
|
||||||
|
*/
|
||||||
public CommandType getType() {
|
public CommandType getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the arguments of the command
|
||||||
|
* @return A list of arguments
|
||||||
|
*/
|
||||||
public List<Object> getArgs() {
|
public List<Object> getArgs() {
|
||||||
return new ArrayList<>(args);
|
return new ArrayList<>(args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,10 @@ package fr.univ.lyon1.common.command;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of command types
|
||||||
|
* @see Command
|
||||||
|
*/
|
||||||
public enum CommandType implements Serializable {
|
public enum CommandType implements Serializable {
|
||||||
login("login", "Login to the server"),
|
login("login", "Login to the server"),
|
||||||
message("message", "Send a message"),
|
message("message", "Send a message"),
|
||||||
|
@ -12,15 +16,29 @@ public enum CommandType implements Serializable {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String description;
|
private final String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command type is defined by a name and a description
|
||||||
|
* @param name the command name
|
||||||
|
* @param description the command description
|
||||||
|
*/
|
||||||
CommandType(String name, String description) {
|
CommandType(String name, String description) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the command
|
||||||
|
* @return the command name
|
||||||
|
*/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the description of the command
|
||||||
|
* @return the command description
|
||||||
|
*/
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
package fr.univ.lyon1.common.exception;
|
package fr.univ.lyon1.common.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main exception of the chat system for client and server communication
|
||||||
|
*/
|
||||||
public class ChatException extends Exception {
|
public class ChatException extends Exception {
|
||||||
|
/**
|
||||||
|
* This exception need only a message
|
||||||
|
* @param message the message
|
||||||
|
*/
|
||||||
public ChatException(String message) {
|
public ChatException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package fr.univ.lyon1.common.exception;
|
package fr.univ.lyon1.common.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception when a login/password is invalid
|
||||||
|
*/
|
||||||
public class LoginInvalid extends ChatException {
|
public class LoginInvalid extends ChatException {
|
||||||
public LoginInvalid(String message) {
|
public LoginInvalid(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package fr.univ.lyon1.common.exception;
|
package fr.univ.lyon1.common.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception when the user is not logged
|
||||||
|
*/
|
||||||
public class LoginRequired extends ChatException {
|
public class LoginRequired extends ChatException {
|
||||||
public LoginRequired() {
|
public LoginRequired() {
|
||||||
super("Login required");
|
super("Login required");
|
||||||
|
|
|
@ -2,6 +2,9 @@ package fr.univ.lyon1.common.exception;
|
||||||
|
|
||||||
import fr.univ.lyon1.common.Channel;
|
import fr.univ.lyon1.common.Channel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception sent to a client when he is not in the target channel
|
||||||
|
*/
|
||||||
public class NotInChannel extends ChatException {
|
public class NotInChannel extends ChatException {
|
||||||
public NotInChannel(Channel channel) {
|
public NotInChannel(Channel channel) {
|
||||||
super("Your not in channel "+channel);
|
super("Your not in channel "+channel);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package fr.univ.lyon1.common.exception;
|
package fr.univ.lyon1.common.exception;
|
||||||
|
|
||||||
import fr.univ.lyon1.common.command.Command;
|
/**
|
||||||
|
* Exception when a command is not known by the client or server
|
||||||
|
*/
|
||||||
public class UnknownCommand extends ChatException {
|
public class UnknownCommand extends ChatException {
|
||||||
public UnknownCommand() {
|
public UnknownCommand() {
|
||||||
super("Command unknown");
|
super("Command unknown");
|
||||||
|
|
Reference in a new issue