Skip to content
Snippets Groups Projects
Commit 6e25094e authored by Ferhat Hocine's avatar Ferhat Hocine
Browse files

rendu final

parent 15fe9301
Branches
Tags
No related merge requests found
Showing
with 572 additions and 158 deletions
Ferhat HOCINE M1gl
#SR2_PROJET2_AgentFlopBox
#Ferhat_HOCINE_M1GL
## 1- Intoduction :
L'objectif du projet est de développer une application cliente pour la plate-forme FlopBox(projet1) qui permette de synchroniser les données stockées à distance dans un ensemble de serveurs FTP avec le système de fichiers local d'une machine sur laquelle l'application cliente sera exécutée.
## 2-Exécution:
a)Server python:
- dans la racine on exécute la commande :
--> python3 server.py
b)Le projet1:
dans la racine du projet1(projet1/FlobBox/) on exécute la commande :
---> mvn package
puis la commande :
---> java -jar target/simple-service-1.0-SNAPSHOT-jar-with-dependencies.jar
on ouvre une nouvelle fenètre du terminal et on exécute la commande :
---> curl --location --request POST 'http://localhost:8080/flopbox/ftp.ubuntu.com'
---> curl --location --request PUT 'http://localhost:8080/flopbox/ftp.ubuntu.com' --header 'alias: ubuntu'
c)Le projet2:
dans la racine du projet1(sr2/flop_box_agent/) on exécute la commande :
---> mvn package
puis la commande :
(export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64)
---> mvn javadoc:javadoc
ensuite :
---> java -jar target/flop_box_agent-1.0-SNAPSHOT.jar
## 3-Architecture
a)-Gestion d'erreur : les erreurs sont gérées par des try, catch qui renvoie des exceptions :
exemple :
'''
public void downloadAll(String alias, User user,String port,String path,String myPath, boolean first) throws ConnectException {
if( first && new File(alias+path).exists()) {
System.out.println("delete folder -> "+myPath);
try {
deleteFolder(alias, user,port, myPath);
} catch (ConnectException e) {
e.printStackTrace();
}
}
System.out.println("create folder -> "+myPath);
try {
createFolder(alias, user,port, myPath);
} catch (ConnectException e) {
throw new ConnectException(e);
}
String response;
try {
response = getList( alias, user, port, path);
} catch (ConnectException e) {
// TODO Auto-generated catch block
throw new ConnectException(e);
}
String[] list=response.split("\n");
for (String line:list) {
String[] myLine=line.split(" ");
String name= myLine[myLine.length -1];
if(line.startsWith("d")) {
if(!name.startsWith(".") && !name.contains(alias)){
downloadAll(alias, user, port, path+"/"+name,myPath+"/"+name, false);
}
}
else {
String mypath1=myPath;
if(myPath.startsWith("sr2/flop_box_agent")) {
mypath1=myPath.replaceFirst("sr2/flop_box_agent/", "");
}
if(name!="") {
String path2=path;
if(path!="" ) {
path2=path+"/";
}
download( alias, user, port, path2 +name,mypath1+"/"+name);
}
}
}
}
'''
on vois dans cette méthode que l'éxception ConnectException est levé si on arrive pas à avoir la liste d'élements avec getList
b) énum :
--> public enum type_folder_file {file, directory
}
cet énum est utilisé afin de distingué entre un fichier et un dossier
---> public enum Download_upload_enum {
donwload, upload
}
cet énum est utilisé afin de distingué entre un l'action donwload et l'action upload que sera utilisé dans la méthode server par l'appel de la méthode upload ou download de la class client.
## 4-Parcours du code (code samples):
a)- client.server :
'''
public String server(String methode,String m_url, HashMap<String, String> header,Download_upload_enum download_upload,String filename) throws ConnectException {
try{
URL url = new URL(m_url);
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
connection.setRequestMethod(methode);
if(header!= null) {
for(Entry<String, String> mapentry : header.entrySet()) {
connection.setRequestProperty(mapentry.getKey(),mapentry.getValue());
}
}
if(download_upload==Download_upload_enum.donwload) {
try (InputStream in= connection.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(filename)) {
int bytesRead;
byte dataBuffer1[] = new byte[1024];
while ((bytesRead = in.read(dataBuffer1, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer1, 0, bytesRead);
}
System.out.println("file downloaded !");
return "";
}
catch (IOException e) {
e.printStackTrace();
}
}
else if(download_upload==Download_upload_enum.upload) {
connection.setDoOutput(true);
connection.setDoInput(true);
BufferedOutputStream bos = new BufferedOutputStream(connection.getOutputStream());
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filename));
int i;
while ((i = bis.read()) > 0) {
bos.write(i);
}
bis.close();
bos.close();
}
else {
BufferedReader read= new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response="";
String line;
while((line=read.readLine())!=null) {
response+=line+"\n";
}
return response;
}
}
catch (IOException e) {
throw new ConnectException(e);
}
System.out.println("Réponse null !");
return "";
}
'''
cette méthode est la méthode principale de la class client elle est utilisé par les autres méthodes afin de comuniquer avec le server.
elle utilise HttpURLConnection pour se connecter au server puis puis lancer une requete graçe à l'url et la méthode passé en paramètre.
puis la réponse est traité selon la méthode qui l'a appeler.
b) client.addServer:
'''
/**
* Add a new server
* @throws ConnectException
*/
public void addServer(String server) throws ConnectException {
server("POST",s_Url+server,null,null,null);
}
'''
addServer est un exemple de méthode qui utilise la méthode server.
c) client.download:
'''
public void download(String alias, User user,String port, String filepath, String repPath) throws ConnectException {
HashMap<String,String> map = new HashMap<String,String>();
map.put("username",user.getIdent());
map.put("password",user.getPassword());
map.put("port",port);
map.put("Content-Disposition", "filename=\"" + repPath + "\"");
int index =filepath.lastIndexOf("/");
String filename;
if(index!=-1) {
filename= filepath.substring(index+1);
}
else {
filename= filepath;
}
System.out.println(server("GET",s_Url+alias+"/file/"+filepath, map,Download_upload_enum.donwload,repPath));
}
'''
la méthode download utilse aussi la méthode server mais en fournissant deux paramètre qui été null dans l'exemple précident.
le premier paramètre est (Download_upload_enum.donwload) pour dire que cette action est un téléchargement et doit etre traiter différemment
d) client.downloadAll :
'''
public void downloadAll(String alias, User user,String port,String path,String myPath, boolean first) throws ConnectException {
if( first && new File(alias+path).exists()) {
System.out.println("delete folder -> "+myPath);
try {
deleteFolder(alias, user,port, myPath);
} catch (ConnectException e) {
e.printStackTrace();
}
}
System.out.println("create folder -> "+myPath);
try {
createFolder(alias, user,port, myPath);
} catch (ConnectException e) {
throw new ConnectException(e);
}
String response;
try {
response = getList( alias, user, port, path);
} catch (ConnectException e) {
// TODO Auto-generated catch block
throw new ConnectException(e);
}
String[] list=response.split("\n");
for (String line:list) {
String[] myLine=line.split(" ");
String name= myLine[myLine.length -1];
if(line.startsWith("d")) {
if(!name.startsWith(".") && !name.contains(alias)){
downloadAll(alias, user, port, path+"/"+name,myPath+"/"+name, false);
}
}
else {
String mypath1=myPath;
if(myPath.startsWith("sr2/flop_box_agent")) {
mypath1=myPath.replaceFirst("sr2/flop_box_agent/", "");
}
if(name!="") {
String path2=path;
if(path!="" ) {
path2=path+"/";
}
download( alias, user, port, path2 +name,mypath1+"/"+name);
}
}
}
'''
cette méthode est utilisé afin de telecharger le contenu d'un server.
elle utilise la méthode getList pour lister les sous élement d'un dossier, parcours ces élément la et télécharge les fichier et en cas de dossier un appel récursive est fait pour traité se dossier de la même façon.
e) myLIstofServers :
'''
/**
* Update Server's List.
*/
public void myListOfServers() {
try{
URL url = new URL(s_Url);
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
BufferedReader read= new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response="";
String line;
while((line=read.readLine())!=null) {
response+=line;
}
response=response.substring(response.indexOf("[")+1, response.indexOf("]"));
if(response.equals("")) {
System.out.println("Liste de server vide");
}
else{
Main.list_alias=new ArrayList<Server>();
String[] list=response.split(",");
for (String server:list) {
server=server.substring(server.indexOf("(")+1, server.indexOf(")")); // pour enlever '(' et ')'
String[] serverALias=server.split(":");
Server s= new Server(serverALias[0],serverALias[1]);
Main.list_alias.add(s);
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
'''
cette méthode récupère la liste des server enregistrer dans le premier projet et enregistre ces dernier dans un liste de la class main de notre projet.
UML.jpg 0 → 100644
UML.jpg

99.4 KiB

......@@ -46,9 +46,8 @@
</plugin>
<plugin>
<groupId>flopboxagent</groupId>
<artifactId>flop_box_agent</artifactId>
<version>1.0-SNAPSHOT</version>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<reportOutputDirectory>${project.build.directory}/docs</reportOutputDirectory>
<destDir>docs</destDir><nohelp>true</nohelp>
......
......@@ -4,6 +4,7 @@ package flopboxagent;
**/
import java.awt.List;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
......@@ -16,36 +17,29 @@ import flopboxagent.client.ConnectException;
import flopboxagent.client.client;
import flopboxagent.client.type_folder_file;
import flopboxagent.server.Server;
import watchService.DirectoryWatcher;
import watchService.WatchDir;
/**
* MAIN class
*/
public class Main {
public static ArrayList<Server> list_alias = new ArrayList<Server>();
public static void main( String[] args ) throws ConnectException, InterruptedException
public static void main( String[] args ) throws ConnectException, InterruptedException, IOException
{
client c= new client();
c.myListOfServers();
c.addServer("localhost");
c.addServerAlias("localhost", "lc");
User user= new User("hocine","ferhat");
String port = "2121";
c.getList("lc",user,port,"");
//c.deleteFolder("lc",user,port,"sr2/flop_box_agent/lc");
//c.download("lc", user, port, "server.py", "myDownload/server2.py");
c.downloadAll("lc",user,port,"","sr2/flop_box_agent/lc", true);
client c= new client(); //création de client
c.addServer("localhost"); //ajout du server localhost
c.addServerAlias("localhost", "lc"); // afectation d'un l'Alias
User user= new User("hocine","ferhat"); //création d'un user
c.myListOfServers(); //récupération de la liste de server
for(Server s:list_alias) {
System.out.println("server : "+s.getServer() +" - Alias : "+s.getAlis());
}
String port = "2121"; // création d'un port
System.out.println(c.getList("lc",user,port,"")); //affichage des élement du server
c.downloadAll("lc",user,port,"","sr2/flop_box_agent/lc", true); //télechargement de tous les élément du server localhost
DirectoryWatcher dirWatcher = new DirectoryWatcher(Paths.get("lc"),c,"lc",user,port);
Thread dirWatcherThread = new Thread(dirWatcher);
dirWatcherThread.start();
Thread.sleep(60000);
dirWatcherThread.interrupt();
/*
ArrayList<String> res=new ArrayList<String>();
res.add("lc");
res.addAll(c.listOfDirectory("lc",user,port,""));
*/
WatchDir w = new WatchDir(Paths.get("lc"), true,c,"lc",user,port); // création d'un instance de la classe WatchDir qui surveille les changement dans le local
w.processEvents(); // éxécution de la classe
}
}
package flopboxagent.User;
/**
* @author Ferhat_HOCINE
**/
/**
......
package flopboxagent.client;
/**
* @author Ferhat_HOCINE
**/
import java.awt.List;
......@@ -280,6 +283,8 @@ public class client {
while ((i = bis.read()) > 0) {
bos.write(i);
}
bis.close();
bos.close();
}
else {
BufferedReader read= new BufferedReader(new InputStreamReader(connection.getInputStream()));
......@@ -299,9 +304,18 @@ public class client {
}
/**
* downloadAll is the methode used to download all from server
* @param String alias
* @param User user
* @param String port
* @param String path
* @param String myPath
* @param boolean first
* @throws ConnectException
*/
public void downloadAll(String alias, User user,String port,String path,String myPath, boolean first) throws ConnectException {
if( first && new File(alias).exists()) {
if( first && new File(alias+path).exists()) {
System.out.println("delete folder -> "+myPath);
try {
deleteFolder(alias, user,port, myPath);
......@@ -351,7 +365,15 @@ public class client {
}
/**
* listOfDirectory is the methode used get all subFolder
* @param String alias
* @param User user
* @param String port
* @param String path
* @return ArrayList<String>
* @throws ConnectException
*/
public ArrayList<String> listOfDirectory(String alias, User user,String port,String path) throws ConnectException {
String response;
ArrayList<String> res = new ArrayList<String>();
......
package flopboxagent.server;
/**
* @author Ferhat_HOCINE
**/
/**
* Class to represent server with an alias to call it
......
package watchService;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import flopboxagent.User.User;
import flopboxagent.client.ConnectException;
import flopboxagent.client.client;
public class DirectoryWatcher implements Runnable {
private Path path;
private client client;
private String alias;
private User user;
private String port;
public DirectoryWatcher(Path path, client c,String alias,User user,String port) {
this.path = path;
this.client = c;
this.alias=alias;
this.user=user;
this.port=port;
}
// print the events and the affected file
private void printEvent(WatchEvent<?> event) throws ConnectException {
Kind<?> kind = event.kind();
if (kind.equals(StandardWatchEventKinds.ENTRY_CREATE)) {
Path pathCreated = (Path) event.context();
this.client.createFolder(this.alias,this.user,this.port,pathCreated.toString());
System.out.println("Entry created:" + pathCreated);
} else if (kind.equals(StandardWatchEventKinds.ENTRY_DELETE)) {
Path pathDeleted = (Path) event.context();
this.client.deleteFolder(this.alias,this.user,this.port,pathDeleted.toString());
System.out.println("Entry deleted:" + pathDeleted);
} else if (kind.equals(StandardWatchEventKinds.ENTRY_MODIFY)) {
Path pathModified = (Path) event.context();
System.out.println("Entry modified:"+ pathModified);
}
}
@Override
public void run() {
try {
WatchService watchService = path.getFileSystem().newWatchService();
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
// loop forever to watch directory
while (true) {
WatchKey watchKey;
watchKey = watchService.take(); // this call is blocking until events are present
// poll for file system events on the WatchKey
for (final WatchEvent<?> event : watchKey.pollEvents()) {
printEvent(event);
}
// if the watched directed gets deleted, get out of run method
if (!watchKey.reset()) {
System.out.println("No longer valid");
watchKey.cancel();
watchService.close();
break;
}
}
} catch (InterruptedException ex) {
System.out.println("end !");
return;
} catch (IOException ex) {
ex.printStackTrace();
return;
} catch (ConnectException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
\ No newline at end of file
package watchService;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
public class DirectoryWatcherExample {
public String path;
public DirectoryWatcherExample(String path) {
this.path=path;
}
public void run() throws IOException, InterruptedException {
WatchService watchService
= FileSystems.getDefault().newWatchService();
Path path = Paths.get(this.path);
path.register(
watchService,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey key;
while ((key = watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println(
"Event kind:" + event.kind()
+ ". File affected: " + event.context() + ".");
}
key.reset();
}
}
}
package watchService;
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.nio.file.*;
import static java.nio.file.StandardWatchEventKinds.*;
import static java.nio.file.LinkOption.*;
import java.nio.file.attribute.*;
import java.io.*;
import java.util.*;
import flopboxagent.User.User;
import flopboxagent.client.ConnectException;
import flopboxagent.client.client;
/**
* Example to watch a directory (or tree) for changes to files.
*/
public class WatchDir {
private client client;
private String alias;
private User user;
private String port;
private final WatchService watcher;
private final Map<WatchKey,Path> keys;
private final boolean recursive;
private boolean trace = false;
@SuppressWarnings("unchecked")
static <T> WatchEvent<T> cast(WatchEvent<?> event) {
return (WatchEvent<T>)event;
}
/**
* Register the given directory with the WatchService
*/
private void register(Path dir) throws IOException {
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
if (trace) {
Path prev = keys.get(key);
if (prev == null) {
System.out.format("register: %s\n", dir);
} else {
if (!dir.equals(prev)) {
System.out.format("update: %s -> %s\n", prev, dir);
}
}
}
keys.put(key, dir);
}
/**
* Register the given directory, and all its sub-directories, with the
* WatchService.
*/
private void registerAll(final Path start) throws IOException {
// register directory and sub-directories
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException
{
register(dir);
return FileVisitResult.CONTINUE;
}
});
}
/**
* Creates a WatchService and registers the given directory
*/
public WatchDir(Path dir, boolean recursive,client c, String alias,User user,String port) throws IOException {
this.watcher = FileSystems.getDefault().newWatchService();
this.keys = new HashMap<WatchKey,Path>();
this.recursive = recursive;
this.client = c;
this.alias=alias;
this.user=user;
this.port=port;
if (recursive) {
System.out.format("Scanning %s ...\n", dir);
registerAll(dir);
System.out.println("Done.");
} else {
register(dir);
}
// enable trace after initial registration
this.trace = true;
}
/**
* Process all events for keys queued to the watcher
* @throws ConnectException
* @throws IOException
*/
public void processEvents() throws ConnectException, IOException {
for (;;) {
// wait for key to be signalled
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException x) {
return;
}
Path dir = keys.get(key);
if (dir == null) {
System.err.println("WatchKey not recognized!!");
continue;
}
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind kind = event.kind();
// TBD - provide example of how OVERFLOW event is handled
if (kind == OVERFLOW) {
continue;
}
// Context for directory entry event is the file name of entry
WatchEvent<Path> ev = cast(event);
Path name = ev.context();
Path child = dir.resolve(name);
if(event.kind()==ENTRY_CREATE) {
System.out.println("1- "+event.kind().name()+" : "+ child);
this.client.createFolder(this.alias,this.user,this.port,child.toString().replaceFirst(this.alias+"/", ""));
}
if(event.kind()==ENTRY_DELETE) {
System.out.println("2- "+ event.kind().name()+" : "+ child);
this.client.deleteFolder(this.alias,this.user,this.port,child.toString().replaceFirst(this.alias+"/", ""));
}
// if directory is created, and watching recursively, then
// register it and its sub-directories
if (recursive && (kind == ENTRY_CREATE)) {
try {
if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
registerAll(child);
}
} catch (IOException x) {
// ignore to keep sample readbale
}
}
}
// reset key and remove from set if directory no longer accessible
boolean valid = key.reset();
if (!valid) {
keys.remove(key);
// all directories are inaccessible
if (keys.isEmpty()) {
break;
}
}
}
}
static void usage() {
System.err.println("usage: java WatchDir [-r] dir");
System.exit(-1);
}
}
File deleted
File deleted
File deleted
File deleted
File deleted
File deleted
File deleted
File deleted
File deleted
File deleted
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment