[SERVEUR] Ajout des logs dans le projet serveur (log4j 2)

This commit is contained in:
Notmoo-PC\Notmoo 2018-01-27 18:58:01 +01:00
parent 2b58cbc635
commit 1dc95fa604
15 changed files with 260 additions and 50 deletions

View File

@ -32,6 +32,23 @@
<version>2.4</version> <version>2.4</version>
</dependency> </dependency>
<!-- Dépendances core et api de log4j (API de logging) -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.10.0</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -29,5 +29,8 @@
<orderEntry type="module" module-name="core" /> <orderEntry type="module" module-name="core" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" /> <orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.4" level="project" /> <orderEntry type="library" name="Maven: commons-io:commons-io:2.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.10.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-core:2.10.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-web:2.10.0" level="project" />
</component> </component>
</module> </module>

View File

@ -3,9 +3,35 @@
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app> <web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<context-param> <context-param>
<param-name>res-file.location</param-name> <param-name>isLog4jAutoInitializationDisabled</param-name>
<param-value>G:\temp\</param-value> <param-value>true</param-value>
</context-param> </context-param>
<context-param>
<param-name>log4jContextName</param-name>
<param-value>pqt-server</param-value>
</context-param>
<filter>
<filter-name>log4jServletFilter</filter-name>
<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>log4jServletFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
<dispatcher>ASYNC</dispatcher><!-- Servlet 3.0 w/ disabled auto-initialization only; not supported in 2.5 -->
</filter-mapping>
<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>
</web-app> </web-app>

View File

@ -21,6 +21,8 @@ import com.pqt.server.module.statistics.StatisticsService;
import com.pqt.server.module.stock.StockService; import com.pqt.server.module.stock.StockService;
import com.pqt.server.tools.io.ISerialFileManager; import com.pqt.server.tools.io.ISerialFileManager;
import com.pqt.server.tools.io.SimpleSerialFileManagerFactory; import com.pqt.server.tools.io.SimpleSerialFileManagerFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.*; import java.util.*;
@ -52,6 +54,8 @@ import java.util.*;
*/ */
public class SimpleMessageHandler implements IMessageHandler { public class SimpleMessageHandler implements IMessageHandler {
private static Logger LOGGER = LogManager.getLogger(SimpleMessageHandler.class);
private final String header_ref_query = "Detail_refus"; private final String header_ref_query = "Detail_refus";
private final String header_err_query = "Detail_erreur"; private final String header_err_query = "Detail_erreur";
@ -70,7 +74,8 @@ public class SimpleMessageHandler implements IMessageHandler {
private MessageManager manager; private MessageManager manager;
public SimpleMessageHandler(String ressourceFolderPathStr) { public SimpleMessageHandler(String ressourceFolderPathStr) {
LOGGER.info("Initialisation du gestionnaire de messages entrant");
LOGGER.info("Emplacement des ressources du serveur : {}", ressourceFolderPathStr);
serverStateService = new ServerStateService(); serverStateService = new ServerStateService();
accountService = new AccountService(ressourceFolderPathStr); accountService = new AccountService(ressourceFolderPathStr);
//clientService = new ClientService(); //clientService = new ClientService();
@ -303,8 +308,10 @@ public class SimpleMessageHandler implements IMessageHandler {
} }
private class MessageManager{ private class MessageManager{
private Set<MessageTypeEntry> entries; private Set<MessageTypeEntry> entries;
MessageManager(){ MessageManager(){
entries = new HashSet<>(); entries = new HashSet<>();
} }
@ -314,6 +321,7 @@ public class SimpleMessageHandler implements IMessageHandler {
} }
void support(MessageType type, IMessageProcess process, AccountLevel permissionLevel, boolean accountConnectionRequired){ void support(MessageType type, IMessageProcess process, AccountLevel permissionLevel, boolean accountConnectionRequired){
LOGGER.info("Ajout du support du type {} pour le niveau {} (connexion requise : {})", type.name(), permissionLevel.name(), accountConnectionRequired);
entries.add(new MessageTypeEntry(type, process, permissionLevel, accountConnectionRequired)); entries.add(new MessageTypeEntry(type, process, permissionLevel, accountConnectionRequired));
} }

View File

@ -3,8 +3,11 @@ package com.pqt.server.module.account;
import com.pqt.core.entities.user_account.Account; import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel; import com.pqt.core.entities.user_account.AccountLevel;
import com.pqt.core.entities.user_account.AccountUpdate; import com.pqt.core.entities.user_account.AccountUpdate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List; import java.util.List;
import java.util.function.Predicate;
//TODO Issue #6 : ajouter logs //TODO Issue #6 : ajouter logs
/** /**
@ -17,6 +20,8 @@ import java.util.List;
*/ */
public class AccountService { public class AccountService {
private static Logger LOGGER = LogManager.getLogger(AccountService.class);
private IAccountDao dao; private IAccountDao dao;
public AccountService(String ressourceFolderPathStr) { public AccountService(String ressourceFolderPathStr) {
@ -70,7 +75,9 @@ public class AccountService {
* @return {@code true} si le changement d'état a eu lieu, {@code false} sinon. * @return {@code true} si le changement d'état a eu lieu, {@code false} sinon.
*/ */
public boolean submitAccountCredentials(Account account, boolean desiredState) { public boolean submitAccountCredentials(Account account, boolean desiredState) {
return dao.submitAccountCredentials(account, desiredState); boolean status = dao.submitAccountCredentials(account, desiredState);
LOGGER.info("Changement d'état : compte '{}', état désiré '{}' --> résultat '{}'", account.getUsername(), desiredState, status);
return status;
} }
/** /**
@ -120,18 +127,44 @@ public class AccountService {
} }
public void applyUpdateList(List<AccountUpdate> updates) { public void applyUpdateList(List<AccountUpdate> updates) {
updates.stream() Predicate<AccountUpdate> predicate = update->
.filter(update->
(update.getOldVersion()!=null && dao.isAccountRegistered(update.getOldVersion())) (update.getOldVersion()!=null && dao.isAccountRegistered(update.getOldVersion()))
|| update.getNewVersion()!=null) || update.getNewVersion()!=null;
updates.stream()
.filter(predicate)
.forEach(update->{ .forEach(update->{
if(update.getNewVersion()==null){ if(update.getNewVersion()==null){
if(!dao.isAccountConnected(update.getOldVersion())) if(!dao.isAccountConnected(update.getOldVersion())){
dao.removeAccount(update.getOldVersion()); if(dao.removeAccount(update.getOldVersion()))
LOGGER.info("Suppression du compte '{}'", update.getOldVersion().getUsername());
else
LOGGER.info("Echec de la suppression du compte '{}'",
update.getOldVersion().getUsername());
}
}else if(update.getOldVersion()==null){ }else if(update.getOldVersion()==null){
dao.addAccount(update.getNewVersion()); if(dao.addAccount(update.getNewVersion()))
LOGGER.info("Ajout du compte '{}'", update.getNewVersion().getUsername());
else
LOGGER.info("Echec de l'ajout du compte '{}'", update.getNewVersion().getUsername());
}else{ }else{
dao.modifyAccount(update.getOldVersion(), update.getNewVersion()); if(dao.modifyAccount(update.getOldVersion(), update.getNewVersion()))
LOGGER.info("Modification du compte '{}'", update.getOldVersion().getUsername());
else
LOGGER.info("Echec de la modification du compte '{}'",
update.getOldVersion().getUsername());
}
});
updates.stream()
.filter(predicate.negate())
.forEach(update->{
if(update.getOldVersion()!=null && update.getNewVersion()!=null){
LOGGER.info("Modification du compte '{}' refusée : préconditions non-remplies", update.getOldVersion().getUsername());
}else if(update.getOldVersion()!=null){
LOGGER.info("Suppression du compte '{}' refusée : préconditions non-remplies", update.getOldVersion().getUsername());
}else if(update.getNewVersion()!=null){
LOGGER.info("Ajout du compte '{}' refusé : préconditions non-remplies", update.getNewVersion().getUsername());
}else{
LOGGER.info("Modification de compte refusée : ancienne et nouvelle version nulles", update.getOldVersion().getUsername());
} }
}); });
} }

View File

@ -169,16 +169,18 @@ public class FileAccountDao implements IAccountDao {
} }
@Override @Override
public synchronized void removeAccount(Account oldVersion) { public synchronized boolean removeAccount(Account oldVersion) {
AccountEntry match = lookupMatchingEntry(oldVersion, accountEntries); AccountEntry match = lookupMatchingEntry(oldVersion, accountEntries);
if(match!=null && !connectedAccount.contains(match)){ if(match!=null && !connectedAccount.contains(match)){
accountEntries.remove(match); accountEntries.remove(match);
saveToFile(); saveToFile();
return true;
} }
return false;
} }
@Override @Override
public synchronized void modifyAccount(Account oldVersion, Account newVersion) { public synchronized boolean modifyAccount(Account oldVersion, Account newVersion) {
AccountEntry match = lookupMatchingEntry(oldVersion, accountEntries); AccountEntry match = lookupMatchingEntry(oldVersion, accountEntries);
if(match!=null && oldVersion.getUsername().equals(newVersion.getUsername())){ if(match!=null && oldVersion.getUsername().equals(newVersion.getUsername())){
boolean toReconnect = connectedAccount.remove(match); boolean toReconnect = connectedAccount.remove(match);
@ -192,7 +194,9 @@ public class FileAccountDao implements IAccountDao {
if(toReconnect) if(toReconnect)
connectedAccount.add(newEntry); connectedAccount.add(newEntry);
saveToFile(); saveToFile();
return true;
} }
return false;
} }
/** /**

View File

@ -78,7 +78,7 @@ public interface IAccountDao {
* *
* @param oldVersion * @param oldVersion
*/ */
void removeAccount(Account oldVersion); boolean removeAccount(Account oldVersion);
/** /**
* Modifie un objet {@link Account} {@code oldVersion} en remplaçant ses attributs par ceux de {@code newVersion}. * Modifie un objet {@link Account} {@code oldVersion} en remplaçant ses attributs par ceux de {@code newVersion}.
@ -89,5 +89,5 @@ public interface IAccountDao {
* @param oldVersion * @param oldVersion
* @param newVersion * @param newVersion
*/ */
void modifyAccount(Account oldVersion, Account newVersion); boolean modifyAccount(Account oldVersion, Account newVersion);
} }

View File

@ -1,6 +1,8 @@
package com.pqt.server.module.client; package com.pqt.server.module.client;
import com.pqt.core.entities.members.Client; import com.pqt.core.entities.members.Client;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
@ -8,8 +10,6 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
//TODO Issue #6 : ajouter logs
/** /**
* Cette classe correspond au service de gestion des clients. * Cette classe correspond au service de gestion des clients.
* <p/> * <p/>
@ -21,6 +21,8 @@ import java.util.stream.Collectors;
*/ */
public class ClientService { public class ClientService {
private static Logger LOGGER = LogManager.getLogger(ClientService.class);
private Set<ClientEntry> clientCache; private Set<ClientEntry> clientCache;
public ClientService(){ public ClientService(){
@ -36,7 +38,7 @@ public class ClientService {
* @return {@code true} si le client donné correspond à une entrée du cache, {@code false} sinon. * @return {@code true} si le client donné correspond à une entrée du cache, {@code false} sinon.
*/ */
public boolean isClientRegistered(Client client) { public boolean isClientRegistered(Client client) {
return clientCache.contains(client); return clientCache.contains(lookupClientEntry(client));
} }
/** /**
@ -46,8 +48,10 @@ public class ClientService {
*/ */
public void registerClient(Client client) { public void registerClient(Client client) {
if(lookupClientEntry(client)==null){ if(lookupClientEntry(client)==null){
LOGGER.info("Ajout du client '{}' au cache", client.getAddress());
clientCache.add(new ClientEntry(client)); clientCache.add(new ClientEntry(client));
}else{ }else{
LOGGER.debug("Rafraichissement du timestamp du client '{}'", client.getAddress());
refreshClientTimestamp(client); refreshClientTimestamp(client);
} }
} }
@ -75,6 +79,7 @@ public class ClientService {
* Vide le cache du service. * Vide le cache du service.
*/ */
public void clear(){ public void clear(){
LOGGER.info("Effaçage du cache client");
clientCache.clear(); clientCache.clear();
} }

View File

@ -1,17 +1,13 @@
package com.pqt.server.module.sale; package com.pqt.server.module.sale;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.sale.LightweightSale; import com.pqt.core.entities.sale.LightweightSale;
import com.pqt.core.entities.sale.Sale; import com.pqt.core.entities.sale.Sale;
import com.pqt.server.module.sale.listeners.ISaleFirerer; import com.pqt.server.module.sale.listeners.ISaleFirerer;
import com.pqt.server.module.sale.listeners.ISaleListener; import com.pqt.server.module.sale.listeners.ISaleListener;
import com.pqt.server.module.sale.listeners.SimpleSaleFirerer; import com.pqt.server.module.sale.listeners.SimpleSaleFirerer;
import com.pqt.server.module.stock.StockService; import com.pqt.server.module.stock.StockService;
import org.apache.logging.log4j.LogManager;
import java.util.HashMap; import org.apache.logging.log4j.Logger;
import java.util.Map;
//TODO Issue #6 : ajouter logs
/** /**
* Cette classe correspond au service de validation des commandes de produits. * Cette classe correspond au service de validation des commandes de produits.
@ -31,6 +27,8 @@ import java.util.Map;
*/ */
public class SaleService { public class SaleService {
private static Logger LOGGER = LogManager.getLogger(SaleService.class);
private ISaleDao dao; private ISaleDao dao;
private ISaleFirerer eventFirerer; private ISaleFirerer eventFirerer;
@ -48,7 +46,21 @@ public class SaleService {
*/ */
public long submitSale(Sale sale) { public long submitSale(Sale sale) {
long id = dao.submitSale(sale); long id = dao.submitSale(sale);
if(id!=-1) eventFirerer.fireSaleValidatedEvent(sale); if(id!=-1){
LOGGER.info("Nouvelle commande : #{}, faite par '{}'(permission {}), de type '{}' et valant {}€",
id,
sale.getOrderedBy().getUsername(),
sale.getOrderedBy().getPermissionLevel().name(),
sale.getType().name(),
sale.getTotalPrice());
eventFirerer.fireSaleValidatedEvent(sale);
}else{
LOGGER.info("Refus d'une commande : faite par '{}'(permission {}), de type '{}' et valant {}€",
sale.getOrderedBy().getUsername(),
sale.getOrderedBy().getPermissionLevel().name(),
sale.getType().name(),
sale.getTotalPrice());
}
return id; return id;
} }
@ -67,7 +79,13 @@ public class SaleService {
Sale sale = dao.convert(lwSale); Sale sale = dao.convert(lwSale);
if(sale!=null) if(sale!=null)
return submitSale(sale); return submitSale(sale);
else
LOGGER.info("Refus d'une lightweight commande : impossible de convertir en commande détaillée\n" +
"Faite par '{}'(premission {}), de type '{}' et valant {}€",
lwSale.getOrderedBy().getUsername(),
lwSale.getOrderedBy().getPermissionLevel().name(),
lwSale.getType().name(),
lwSale.getPrice());
return -1; return -1;
} }
@ -89,9 +107,14 @@ public class SaleService {
* @return {@code true} si la commande a bel et bien été annulée, {@code false} si aucun changement n'a été fait. * @return {@code true} si la commande a bel et bien été annulée, {@code false} si aucun changement n'a été fait.
*/ */
public boolean submitSaleRevert(long id) { public boolean submitSaleRevert(long id) {
if(isSaleRevertSupported()) if(isSaleRevertSupported()){
return dao.submitSaleRevert(id); boolean status = dao.submitSaleRevert(id);
if(status)
LOGGER.info("Revert de la commande #{}", id);
else else
LOGGER.info("Echec du revert de la commande #{}", id);
return status;
}else
throw new UnsupportedOperationException("Cette opération ('sale revert') n'est pas supportée par la configuration actuelle du serveur"); throw new UnsupportedOperationException("Cette opération ('sale revert') n'est pas supportée par la configuration actuelle du serveur");
} }

View File

@ -6,19 +6,21 @@ import com.pqt.core.entities.sale.Sale;
import com.pqt.server.module.sale.listeners.SaleListenerAdapter; import com.pqt.server.module.sale.listeners.SaleListenerAdapter;
import com.pqt.server.module.stock.StockService; import com.pqt.server.module.stock.StockService;
import com.pqt.server.module.sale.SaleService; import com.pqt.server.module.sale.SaleService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
//TODO Issue #6 : Ajouter logs
/** /**
* Cette classe correspond au sservices de statistiques du serveur, chargé de calculer et de mettre à disposition * Cette classe correspond au sservices de statistiques du serveur, chargé de calculer et de mettre à disposition
* diverses données concernant les ventes effectuées et les produits vendus. * diverses données concernant les ventes effectuées et les produits vendus.
*/ */
public class StatisticsService { public class StatisticsService {
private static Logger LOGGER = LogManager.getLogger(StatisticsService.class);
private StockService stockService; private StockService stockService;
private int totalSaleAmount, staffSaleAmount, guestSaleAmount; private int totalSaleAmount, staffSaleAmount, guestSaleAmount;
@ -39,6 +41,7 @@ public class StatisticsService {
saleService.addListener(new SaleListenerAdapter() { saleService.addListener(new SaleListenerAdapter() {
@Override @Override
public void onSaleValidatedEvent(Sale sale) { public void onSaleValidatedEvent(Sale sale) {
LOGGER.info("Mise à jour des statistiques suite à une vente");
double price = sale.getTotalPrice(), worth = sale.getTotalWorth(); double price = sale.getTotalPrice(), worth = sale.getTotalWorth();
totalSaleWorth+=worth; totalSaleWorth+=worth;
totalMoneyMade+=price; totalMoneyMade+=price;

View File

@ -4,11 +4,11 @@ import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.product.ProductUpdate; import com.pqt.core.entities.product.ProductUpdate;
import com.pqt.server.exception.ServerQueryException; import com.pqt.server.exception.ServerQueryException;
import com.pqt.server.tools.entities.SaleContent; import com.pqt.server.tools.entities.SaleContent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List; import java.util.List;
//TODO Issue #6 : ajouter logs
/** /**
* Cette classe correspond au service de gestion du stock de produits. Il est en charge de la persistance des * Cette classe correspond au service de gestion du stock de produits. Il est en charge de la persistance des
* données liées aux produits, de founir un accès centralisé à ces données et se charge également d'appliquer les * données liées aux produits, de founir un accès centralisé à ces données et se charge également d'appliquer les
@ -25,6 +25,8 @@ import java.util.List;
*/ */
public class StockService { public class StockService {
private static Logger LOGGER = LogManager.getLogger(StockService.class);
private IStockDao dao; private IStockDao dao;
public StockService(String ressourceFolderPathStr) { public StockService(String ressourceFolderPathStr) {
@ -48,9 +50,9 @@ public class StockService {
if(upd.getOldVersion()==null){ if(upd.getOldVersion()==null){
addProduct(upd.getNewVersion()); addProduct(upd.getNewVersion());
}else if(upd.getNewVersion()==null){ }else if(upd.getNewVersion()==null){
removeProduct(upd.getOldVersion().getId()); removeProduct(upd.getOldVersion());
}else if(upd.getOldVersion()!=null && upd.getNewVersion()!=null){ }else if(upd.getOldVersion()!=null && upd.getNewVersion()!=null){
modifyProduct(upd.getOldVersion().getId(), upd.getNewVersion()); modifyProduct(upd.getOldVersion(), upd.getNewVersion());
}else{ }else{
throw new ServerQueryException("Object ProductUpdate invalide : old et new valent tous les deux null"); throw new ServerQueryException("Object ProductUpdate invalide : old et new valent tous les deux null");
} }
@ -58,14 +60,16 @@ public class StockService {
} }
private void addProduct(Product product) { private void addProduct(Product product) {
dao.addProduct(product); LOGGER.info("Ajout du produit '{}' --> id #{}", product.getName(), dao.addProduct(product));
} }
private void removeProduct(long id) { private void removeProduct(Product product) {
dao.removeProduct(id); LOGGER.info("Suppression du produit #{} --> '{}'", product.getId(), product.getName());
dao.removeProduct(product.getId());
} }
private void modifyProduct(long id, Product product) { private void modifyProduct(Product oldVersion, Product newVersion) {
dao.modifyProduct(id, product); LOGGER.info("Modification du produit #{} --> '{}'", oldVersion.getId());
dao.modifyProduct(oldVersion.getId(), newVersion);
} }
} }

View File

@ -6,8 +6,8 @@ import com.pqt.core.entities.messages.Message;
import com.pqt.server.controller.IMessageHandler; import com.pqt.server.controller.IMessageHandler;
import com.pqt.server.controller.SimpleMessageHandler; import com.pqt.server.controller.SimpleMessageHandler;
import com.pqt.server.servlets.exceptions.BadPqtServerSetupException; import com.pqt.server.servlets.exceptions.BadPqtServerSetupException;
import com.pqt.server.tools.io.ISerialFileManager; import org.apache.logging.log4j.LogManager;
import com.pqt.server.tools.io.SimpleSerialFileManagerFactory; import org.apache.logging.log4j.Logger;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet; import javax.servlet.annotation.WebServlet;
@ -15,13 +15,13 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; import java.net.URLDecoder;
//TODO Issue #6 : ajouter logs
@WebServlet(name = "QueryServlet", urlPatterns = "/") @WebServlet(name = "QueryServlet", urlPatterns = "/")
public class QueryServlet extends HttpServlet { public class QueryServlet extends HttpServlet {
private static Logger LOGGER = LogManager.getLogger(QueryServlet.class);
private IMessageToolFactory messageToolFactory; private IMessageToolFactory messageToolFactory;
private IMessageHandler msgHandler; private IMessageHandler msgHandler;
@ -37,13 +37,15 @@ public class QueryServlet extends HttpServlet {
executeServletProcess(request, response); executeServletProcess(request, response);
} }
private void executeServletProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { private void executeServletProcess(HttpServletRequest request, HttpServletResponse response) throws IOException {
try { try {
if (this.getServletContext().getRealPath("/WEB-INF/classes") == null) { if (this.getServletContext().getRealPath("/WEB-INF/classes") == null) {
response.getWriter().write(new BadPqtServerSetupException("Real path of ressource folder is null. Current PQT server only works with web server that unpack webapps' WAR files.").toString()); response.getWriter().write(new BadPqtServerSetupException("Real path of ressource folder is null. Current PQT server only works with web server that unpack webapps' WAR files.").toString());
} else { } else {
if (messageToolFactory == null) if (messageToolFactory == null){
LOGGER.debug("Initialisation de la fabrique de messages");
this.messageToolFactory = new GSonMessageToolFactory(); this.messageToolFactory = new GSonMessageToolFactory();
}
if (msgHandler == null) { if (msgHandler == null) {
/* /*
@ -54,26 +56,37 @@ public class QueryServlet extends HttpServlet {
} }
if (request.getQueryString() != null && !request.getQueryString().isEmpty() && request.getParameter("message") != null) { if (request.getQueryString() != null && !request.getQueryString().isEmpty() && request.getParameter("message") != null) {
try { try {
LOGGER.debug("Réception d'un message");
String messageToHandle; String messageToHandle;
if(request.getParameter("encode")!=null) if(request.getParameter("encode")!=null){
LOGGER.debug("Tentative de décodage du message ({})", request.getParameter("encode"));
messageToHandle = URLDecoder.decode(request.getParameter("message"), request.getParameter("encode")); messageToHandle = URLDecoder.decode(request.getParameter("message"), request.getParameter("encode"));
else }else
messageToHandle = request.getParameter("message"); messageToHandle = request.getParameter("message");
Message resp = msgHandler.handleMessage(messageToolFactory.getObjectParser(Message.class).parse(request.getParameter("message"))); Message msg = messageToolFactory.getObjectParser(Message.class).parse(messageToHandle);
LOGGER.debug("Traitement du message (type : '{}', auteur : '{}')", msg.getType(), msg.getUser().getUsername());
Message resp = msgHandler.handleMessage(msg);
LOGGER.debug("Envoi de la réponse (type : '{}')", resp.getType());
response.getWriter().write(messageToolFactory.getObjectFormatter(Message.class).format(resp)); response.getWriter().write(messageToolFactory.getObjectFormatter(Message.class).format(resp));
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("Exception durant le traitement du message : {}", e);
e.printStackTrace(); e.printStackTrace();
response.getWriter().write(String.format("%s : %s", e.getClass().getName(), e.getMessage())); response.getWriter().write(String.format("%s : %s", e.getClass().getName(), e.getMessage()));
response.getWriter().write("StackTrace :"); response.getWriter().write("StackTrace :");
e.printStackTrace(response.getWriter()); e.printStackTrace(response.getWriter());
} }
} else { } else {
LOGGER.error("Message reçu mais incorrectement construit");
response.getWriter().write("Query message was not correctly made : " + request.getQueryString()); response.getWriter().write("Query message was not correctly made : " + request.getQueryString());
} }
} }
}catch (Throwable e){ }catch (Throwable e){
LOGGER.error("Exception ou erreur durant l'exécution du processus du QueryServlet : {}", e);
e.printStackTrace(); e.printStackTrace();
response.getWriter().write(e.toString()); response.getWriter().write(e.toString());
} }

View File

@ -1,5 +1,8 @@
package com.pqt.server.tools; package com.pqt.server.tools;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@ -7,6 +10,8 @@ import java.nio.file.Paths;
public class FileUtil { public class FileUtil {
private static Logger LOGGER = LogManager.getLogger(FileUtil.class);
/** /**
* @see #createFileIfNotExist(Path) * @see #createFileIfNotExist(Path)
*/ */
@ -24,6 +29,7 @@ public class FileUtil {
*/ */
public static boolean createFileIfNotExist(Path filePath) throws IOException { public static boolean createFileIfNotExist(Path filePath) throws IOException {
if(!FileUtil.exist(filePath)){ if(!FileUtil.exist(filePath)){
LOGGER.debug("Création du ficher '{}'", filePath.toAbsolutePath().toString());
Files.createFile(filePath); Files.createFile(filePath);
return true; return true;
} }

View File

@ -1,6 +1,8 @@
package com.pqt.server.tools.io; package com.pqt.server.tools.io;
import com.pqt.server.tools.FileUtil; import com.pqt.server.tools.FileUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.*; import java.io.*;
import java.nio.file.Path; import java.nio.file.Path;
@ -10,6 +12,8 @@ import java.util.*;
//TODO vérifier que le save écrase bien le contenu précédent du fichier //TODO vérifier que le save écrase bien le contenu précédent du fichier
public class SimpleSerialFileManager<T> implements ISerialFileManager<T> { public class SimpleSerialFileManager<T> implements ISerialFileManager<T> {
private static Logger LOGGER = LogManager.getLogger(SimpleSerialFileManager.class);
private Path filePath; private Path filePath;
private Class<T> clazz; private Class<T> clazz;
@ -18,11 +22,13 @@ public class SimpleSerialFileManager<T> implements ISerialFileManager<T> {
} }
SimpleSerialFileManager(Path filePath, Class<T> clazz){ SimpleSerialFileManager(Path filePath, Class<T> clazz){
LOGGER.info("Gestionnaire de fichiers créé pour le fichier '{}'", filePath.toAbsolutePath().toString());
this.filePath = filePath; this.filePath = filePath;
this.clazz = clazz; this.clazz = clazz;
try{ try{
FileUtil.createFileIfNotExist(filePath); FileUtil.createFileIfNotExist(filePath);
}catch (IOException e){ }catch (IOException e){
LOGGER.error("IOException durant la création d'un fichier : {}", e);
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -31,11 +37,13 @@ public class SimpleSerialFileManager<T> implements ISerialFileManager<T> {
public List<T> loadListFromFile() { public List<T> loadListFromFile() {
try{ try{
if(!FileUtil.createFileIfNotExist(filePath)){ if(!FileUtil.createFileIfNotExist(filePath)){
LOGGER.debug("Chargement des données (liste) du fichier '{}'", filePath.toAbsolutePath().toString());
List<T> loadedEntries = new ArrayList<>(); List<T> loadedEntries = new ArrayList<>();
fillCollection(loadedEntries); fillCollection(loadedEntries);
return loadedEntries; return loadedEntries;
} }
}catch(IOException | ClassNotFoundException e){ }catch(IOException | ClassNotFoundException e){
onLoadError(e);
e.printStackTrace(); e.printStackTrace();
} }
return new ArrayList<>(); return new ArrayList<>();
@ -45,11 +53,13 @@ public class SimpleSerialFileManager<T> implements ISerialFileManager<T> {
public Set<T> loadSetFromFile() { public Set<T> loadSetFromFile() {
try{ try{
if(!FileUtil.createFileIfNotExist(filePath)){ if(!FileUtil.createFileIfNotExist(filePath)){
LOGGER.debug("Chargement des données (set) du fichier '{}'", filePath.toAbsolutePath().toString());
Set<T> loadedEntries = new HashSet<>(); Set<T> loadedEntries = new HashSet<>();
fillCollection(loadedEntries); fillCollection(loadedEntries);
return loadedEntries; return loadedEntries;
} }
}catch(IOException | ClassNotFoundException e){ }catch(IOException | ClassNotFoundException e){
onLoadError(e);
e.printStackTrace(); e.printStackTrace();
} }
return new HashSet<>(); return new HashSet<>();
@ -88,21 +98,39 @@ public class SimpleSerialFileManager<T> implements ISerialFileManager<T> {
try{ try{
FileUtil.createFileIfNotExist(filePath); FileUtil.createFileIfNotExist(filePath);
}catch (IOException e){ }catch (IOException e){
onSaveError(e);
e.printStackTrace(); e.printStackTrace();
return; return;
} }
try(FileOutputStream fos = new FileOutputStream(filePath.toString()); try(FileOutputStream fos = new FileOutputStream(filePath.toString());
ObjectOutputStream oos = new ObjectOutputStream(fos)){ ObjectOutputStream oos = new ObjectOutputStream(fos)){
LOGGER.debug("Sauvegarde de données vers le fichier '{}'", filePath.toAbsolutePath().toString());
collection.forEach(p -> { collection.forEach(p -> {
try { try {
oos.writeObject(p); oos.writeObject(p);
} catch (IOException e) { } catch (IOException e) {
onSaveError(e);
e.printStackTrace(); e.printStackTrace();
} }
}); });
}catch(IOException e){ }catch(IOException e){
onSaveError(e);
e.printStackTrace(); e.printStackTrace();
} }
} }
private void onLoadError(Throwable e){
LOGGER.error("Exception durant le chargement des données du fichier '{}' : {} --> {}",
filePath.toAbsolutePath().toString(),
e.getClass().getName(),
e.getMessage());
}
private void onSaveError(Throwable e){
LOGGER.error("Exception durant la sauvegarde de données vers le fichier '{}' : {} --> {}",
filePath.toAbsolutePath().toString(),
e.getClass().getName(),
e.getMessage());
}
} }

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="redux_log_filename">PQT/logs/serveur-redux.log</Property>
<Property name="full_log_filename">PQT/logs/serveur-full.log</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="Redux-File" fileName="${redux_log_filename}">
<PatternLayout>
<pattern>%d %p %C{1.} [%t] %m%n</pattern>
</PatternLayout>
</File>
<File name="Full-File" fileName="${full_log_filename}">
<PatternLayout>
<pattern>%d %p %C{1.} [%t] %m%n</pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
</Root>
<Logger name="com.pqt.server" level="all" additivity="true">
<AppenderRef ref="Full-File"/>
</Logger>
<Logger name="com.pqt.server" level="debug" additivity="true">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="com.pqt.server" level="info" additivity="true">
<AppenderRef ref="Redux-File"/>
</Logger>
</Loggers>
</Configuration>