Merge branch 'benjamin' into dev

This commit is contained in:
Benjamin 2022-03-06 17:31:07 +01:00
commit c6f8025d4b
18 changed files with 191 additions and 28 deletions

View File

@ -10,8 +10,7 @@ import lightcontainer.protocol.rules.reader.FilelistRule;
import lightcontainer.protocol.rules.reader.HelloRule;
import lightcontainer.protocol.rules.reader.SavefileRule;
import lightcontainer.protocol.rules.reader.SigninRule;
import lightcontainer.protocol.rules.writer.SignErrorRule;
import lightcontainer.protocol.rules.writer.SignOkRule;
import lightcontainer.protocol.rules.writer.*;
import lightcontainer.repository.ClientHandlerRepository;
import lightcontainer.repository.FileFrontEnd;
import lightcontainer.repository.ProtocolRepositoryImpl;
@ -62,12 +61,15 @@ public class App {
ProtocolRepository protocolRep = new ProtocolRepositoryImpl();
protocolRep.addReader(new HelloRule());
protocolRep.addReader(new SigninRule());
protocolRep.addReader(new FilelistRule());
protocolRep.addReader(new SavefileRule());
protocolRep.addReader(new SigninRule(protocolRep));
protocolRep.addReader(new FilelistRule(protocolRep));
protocolRep.addReader(new SavefileRule(protocolRep));
protocolRep.addWriter(new SignOkRule());
protocolRep.addWriter(new SignErrorRule());
protocolRep.addWriter(new FilesRule());
protocolRep.addWriter(new SaveFileOkRule());
protocolRep.addWriter(new SaveFileErrorRule());
new UnicastServerListener(clientRep, protocolRep, UNICAST_PORT);
new MulticastServerListener(storeRep, protocolRep, MULTICAST_IP, MULTICAST_PORT);

View File

@ -5,7 +5,6 @@ import lightcontainer.enumerations.TaskType;
public class Task {
// Variables
private TaskType type; // TODO : Supprimer car innutile ?
private TaskStatus status;
private String command;
private String client;
@ -21,4 +20,21 @@ public class Task {
Task task = new Task(TaskStatus.PENDING, command, client);
return task;
}
/**
* Permet de savoir si la réponse est destinée au client
* @param storeDomain Nom du store back end fournissant la réponse.
* @return TRUE si le client doit recevoir cette réponse.
*/
public boolean isResponseOfClient(String storeDomain) {
return (this.storeDomain == storeDomain && status == TaskStatus.PENDING);
}
/**
* Permet de récupérer le login du client associé à la tâche
* @return Login du client
*/
public String getClient() {
return client;
}
}

View File

@ -41,6 +41,7 @@ public class ClientHandler implements Runnable, AutoCloseable {
private BufferedReader reader;
private PrintWriter writer;
private ProtocolWriter.ProtocolResult response;
// Constructor
public ClientHandler(Socket client, ClientHandlerFFE ffe, ProtocolRepository protocolRep) {
@ -86,20 +87,27 @@ public class ClientHandler implements Runnable, AutoCloseable {
while (this.client_run) {
try {
String command = this.reader.readLine();
// TODO gestion de la réception de commandes, fichier, ...
if (command != null) System.out.println("Client: " + command);
ProtocolReader.ProtocolResult ruleResult = protocolRep.executeReader(command + "\r\n");
if (isConnected()) {
ProtocolWriter.ProtocolResult writerCommand = ruleResult.getResultCommand();
ruleResult.read(
this.client.getInputStream()
);
if (ruleResult.getReceiver() == ProtocolReader.ResultCmdReceiver.STOREBACKEND) {
fileFrontEnd.newCommand(command, ruleResult.getResultCommand()); // Envoie dans la file de tâche FileFrontEnd en attente d'un traitement d'un StorBackEnd
fileFrontEnd.newCommand(command, writerCommand.getCommand()); // Envoie dans la file de tâche FileFrontEnd en attente d'un traitement d'un StorBackEnd
// Attend la fin de la réalisation de la tâche
waitTaskResponse();
writer.write(response.getCommand()); // Renvoye au client
writer.flush();
response.write(this.client.getOutputStream()); // Ecrit au client si nécessaire
} else {
writer.write(ruleResult.getResultCommand()); // Renvoye au client
writer.write(writerCommand.getCommand()); // Renvoye au client
writer.flush();
}
@ -107,6 +115,25 @@ public class ClientHandler implements Runnable, AutoCloseable {
authentication(ruleResult);
}
} catch (IOException ignore) { }
}
}
/**
* Permet au Client d'attendre la fin de la réalisation de sa tâche
*/
private void waitTaskResponse() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
public void respond(ProtocolWriter.ProtocolResult response) {
this.response = response;
synchronized (this) {
this.notify();
}
}

View File

@ -79,7 +79,7 @@ public class StoreProcessor extends Thread implements AutoCloseable {
this.client_run = true;
while (this.client_run) {
try {
alertAvalaible();
waitAction();
// Request
ProtocolWriter.ProtocolResult requestResult = protocolRep.executeWriter(this.currentCommand);
@ -92,8 +92,11 @@ public class StoreProcessor extends Thread implements AutoCloseable {
if (responseCommand != null)
System.out.println("StoreBackEnd: " + responseCommand);
ProtocolReader.ProtocolResult responseResult = protocolRep.executeReader(responseCommand);
responseResult.read(this.store.getInputStream());
System.out.println("StoreBackEnd response to client: " + responseResult.getResultCommand());
alertAvalaible(responseResult.getResultCommand());
// TODO : Faire en sorte que getResultCommand retourne un ProtocolWriter
} catch (IOException ignore) { }
}
@ -113,12 +116,20 @@ public class StoreProcessor extends Thread implements AutoCloseable {
/**
* Permet de déclarer le StoreBackEnd disponible
*/
private void alertAvalaible() {
private void alertAvalaible(ProtocolWriter.ProtocolResult responseCommand) {
synchronized (this) {
waitAction();
this.currentCommand = null;
fileFrontEnd.onStoreAvailable(this);
fileFrontEnd.onStoreAvailable(this, responseCommand);
}
}
/**
* Permet au Store d'attendre une action à réaliser
*/
private void waitAction() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) { e.printStackTrace(); }

View File

@ -6,8 +6,22 @@ import lightcontainer.domains.Task;
* Enumeration defining the status of a {@link Task}.
*/
public enum TaskStatus {
/**
* En attente d'être traitée
*/
PENDING,
/**
* En train d'être traitée
*/
PROCESSING,
/**
* Une erreur est survenue
*/
ERROR,
SUCCESS
}

View File

@ -1,6 +1,7 @@
package lightcontainer.interfaces;
import lightcontainer.domains.client.StoreProcessor;
import lightcontainer.protocol.ProtocolWriter;
import lightcontainer.repository.FileFrontEnd;
/**
@ -10,6 +11,7 @@ public interface StoreProcessorFFE {
/**
* Allows a {@link StoreProcessor} to notify the FFE that it's available.
* @param store The store processor that is now available.
* @param responseCommand
*/
void onStoreAvailable(StoreProcessor store);
void onStoreAvailable(StoreProcessor store, ProtocolWriter.ProtocolResult response);
}

View File

@ -3,6 +3,7 @@ package lightcontainer.interfaces;
import lightcontainer.domains.client.ClientHandler;
import lightcontainer.domains.server.MulticastServerListener;
import lightcontainer.domains.server.UnicastServerListener;
import lightcontainer.protocol.ProtocolWriter;
import lightcontainer.repository.ClientHandlerRepository;
/**
@ -20,4 +21,6 @@ public interface UnicastCHR {
* @param client Client Handler to add.
*/
void addClient(ClientHandler client);
void respondToClient(String client, ProtocolWriter.ProtocolResult response);
}

View File

@ -27,7 +27,7 @@ public abstract class ProtocolReader {
/**
* Command qui sera renvoyée par exemple au client
*/
private String resultCommand;
private ProtocolWriter.ProtocolResult resultCommand;
/**
* Désigne vers ou cette commande est envoyée.
@ -44,7 +44,7 @@ public abstract class ProtocolReader {
* Récupérer la commande à envoyer
* @return Commande
*/
public String getResultCommand() {
public ProtocolWriter.ProtocolResult getResultCommand() {
return resultCommand;
}
@ -53,7 +53,7 @@ public abstract class ProtocolReader {
* @param resultCommand Commande à envoyer
* @param receiver Le receveur de cette commande
*/
public void setResultCommand(String resultCommand, ResultCmdReceiver receiver) {
public void setResultCommand(ProtocolWriter.ProtocolResult resultCommand, ResultCmdReceiver receiver) {
this.resultCommand = resultCommand;
this.receiver = receiver;
}

View File

@ -60,7 +60,7 @@ public abstract class ProtocolWriter {
Matcher ruleMatcher = this.rulePattern.matcher(command); // Vérifie que tout match (cf. Matcher). Si match alors on retourne la commande build, sinon on retourne NULL
if (ruleMatcher.matches()) {
ProtocolResult result = onExecuted();
ProtocolResult result = onExecuted(data);
result.setCommand(command);
return (T) result;
}
@ -70,6 +70,8 @@ public abstract class ProtocolWriter {
/**
* Cette méthode est appelée lors de l'exécution de la règle
*/
protected abstract <T extends ProtocolResult> T onExecuted();
protected <T extends ProtocolResult> T onExecuted(String... data) {
return (T) new ProtocolResult();
}
}

View File

@ -1,14 +1,21 @@
package lightcontainer.protocol.rules.reader;
import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.protocol.ProtocolReader;
import lightcontainer.protocol.ProtocolWriter;
import lightcontainer.protocol.rules.writer.FilesRule;
import lightcontainer.protocol.rules.writer.SignOkRule;
public class FilelistRule extends ProtocolReader {
// Constants
private static final String PATTERN = "^FILELIST\r\n$";
private ProtocolRepository protocolRep;
// Constructor
public FilelistRule() {
public FilelistRule(ProtocolRepository protocolRep) {
super(PATTERN);
this.protocolRep = protocolRep;
}
public class Result extends ProtocolResult { }
@ -20,7 +27,7 @@ public class FilelistRule extends ProtocolReader {
@Override
protected FilelistRule.Result onExecuted(String... data) {
FilelistRule.Result result = new Result();
result.setResultCommand("FILES endbenja.txt!500\r\n", ResultCmdReceiver.CLIENT);
result.setResultCommand(this.protocolRep.executeWriter(FilesRule.NAME, "endbenja.txt!500"), ResultCmdReceiver.CLIENT);
return result;
}
}

View File

@ -1,6 +1,9 @@
package lightcontainer.protocol.rules.reader;
import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.protocol.ProtocolReader;
import lightcontainer.protocol.rules.writer.SaveFileErrorRule;
import lightcontainer.protocol.rules.writer.SaveFileOkRule;
import lightcontainer.utils.FileReceiver;
import java.io.IOException;
@ -12,9 +15,12 @@ public class SavefileRule extends ProtocolReader {
private static final int FILE_NAME = 0; // Index file name.
private static final int FILE_SIZE = 1; // Index file size.
private ProtocolRepository protocolRep;
// Constructor
public SavefileRule() {
public SavefileRule(ProtocolRepository protocolRep) {
super(PATTERN);
this.protocolRep = protocolRep;
}
public class Result extends ProtocolResult {
@ -38,9 +44,9 @@ public class SavefileRule extends ProtocolReader {
if (!fileReceiver.receiveFile(reader, this.filename, this.size))
throw new IOException();
this.setResultCommand("SAVEFILE_OK\r\n", ResultCmdReceiver.CLIENT);
this.setResultCommand(protocolRep.executeWriter(SaveFileOkRule.NAME), ResultCmdReceiver.CLIENT);
} catch (IOException e) {
this.setResultCommand("SAVEFILE_ERROR\r\n", ResultCmdReceiver.CLIENT);
this.setResultCommand(protocolRep.executeWriter(SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
e.printStackTrace();
}
}

View File

@ -1,6 +1,9 @@
package lightcontainer.protocol.rules.reader;
import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.protocol.ProtocolReader;
import lightcontainer.protocol.rules.writer.SignErrorRule;
import lightcontainer.protocol.rules.writer.SignOkRule;
import java.io.InputStream;
@ -10,9 +13,12 @@ public class SigninRule extends ProtocolReader {
private static final int LOGIN = 0; // Index du domain dans le tableau de données
private static final int PASSWORD = 1; // Index du port dans le tableau de données
private ProtocolRepository protocolRep;
// Constructor
public SigninRule() {
public SigninRule(ProtocolRepository protocolRep) {
super(PATTERN);
this.protocolRep = protocolRep;
}
public class Result extends ProtocolResult {
@ -50,9 +56,9 @@ public class SigninRule extends ProtocolReader {
// TODO : Création d'une règle d'écriture SIGN_OK et SIGN_ERROR proprement
if (result.checkCredentials()) {
result.setResultCommand("SIGN_OK\r\n", ResultCmdReceiver.CLIENT);
result.setResultCommand(this.protocolRep.executeWriter(SignOkRule.NAME), ResultCmdReceiver.CLIENT);
} else {
result.setResultCommand("SIGN_ERROR\r\n", ResultCmdReceiver.CLIENT);
result.setResultCommand(this.protocolRep.executeWriter(SignErrorRule.NAME), ResultCmdReceiver.CLIENT);
}
return result;
}

View File

@ -0,0 +1,15 @@
package lightcontainer.protocol.rules.writer;
import lightcontainer.protocol.ProtocolWriter;
public class FilesRule extends ProtocolWriter {
private static final String PATTERN = "^FILES(( [^ !]{1,20})!([0-9]{1,10})){0,50}\r\n$";
public static final String NAME = "FILES";
public FilesRule() {
super(NAME, PATTERN);
}
}

View File

@ -0,0 +1,15 @@
package lightcontainer.protocol.rules.writer;
import lightcontainer.protocol.ProtocolWriter;
public class SaveFileErrorRule extends ProtocolWriter {
private static final String PATTERN = "^SAVEFILE_ERROR\r\n$";
public static final String NAME = "SAVEFILE_ERROR";
public SaveFileErrorRule() {
super(NAME, PATTERN);
}
}

View File

@ -0,0 +1,15 @@
package lightcontainer.protocol.rules.writer;
import lightcontainer.protocol.ProtocolWriter;
public class SaveFileOkRule extends ProtocolWriter {
private static final String PATTERN = "^SAVEFILE_OK\r\n$";
public static final String NAME = "SAVEFILE_OK";
public SaveFileOkRule() {
super(NAME, PATTERN);
}
}

View File

@ -11,4 +11,5 @@ public class SignErrorRule extends ProtocolWriter {
public SignErrorRule() {
super(NAME, PATTERN);
}
}

View File

@ -3,6 +3,7 @@ package lightcontainer.repository;
import lightcontainer.domains.client.ClientHandler;
import lightcontainer.domains.server.UnicastServerListener;
import lightcontainer.interfaces.UnicastCHR;
import lightcontainer.protocol.ProtocolWriter;
import java.util.ArrayList;
import java.util.List;
@ -54,6 +55,13 @@ public class ClientHandlerRepository implements AutoCloseable, UnicastCHR {
this.handlers.add(client);
}
@Override
public void respondToClient(String login, ProtocolWriter.ProtocolResult response) {
for (ClientHandler client : handlers) {
client.respond(response);
}
}
/**
* AutoClosable Function
* Closes all ClientHandlers stored in this repository and deallocates all resources.

View File

@ -5,8 +5,10 @@ import lightcontainer.domains.Task;
import lightcontainer.interfaces.ClientHandlerFFE;
import lightcontainer.interfaces.ProtocolRepository;
import lightcontainer.interfaces.StoreProcessorFFE;
import lightcontainer.protocol.ProtocolWriter;
import java.util.Deque;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedDeque;
public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
@ -28,16 +30,27 @@ public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
*/
public void alertStoreProcessors(Task task) {
// On avertit les stor processors d'une nouvelle tâche
}
/**
* Permet à un {@link StoreProcessor} d'avertir le FFE qu'il est disponible
*
* @param store
* @param store Le SBE qui s'est occupé de la tâche
* @param response La réponse à envoyer au client
*/
@Override
public void onStoreAvailable(StoreProcessor store) {
public void onStoreAvailable(StoreProcessor store, ProtocolWriter.ProtocolResult response) {
// TODO : Chercher une tâche appropriée
Iterator<Task> it = tasks.iterator();
while (it.hasNext()) {
Task task = it.next();
if (task.isResponseOfClient(store.getName())) {
clientRepository.respondToClient(task.getClient(), response);
it.remove(); // Suppression de la tâche
}
}
}
@Override