176 lines
5.2 KiB
Java
176 lines
5.2 KiB
Java
package Classes;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.DataOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.URL;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.Map;
|
|
|
|
import org.json.JSONException;
|
|
import org.json.JSONObject;
|
|
|
|
import Interfaces.Callback;
|
|
import Interfaces.DelayedCallback;
|
|
import Interfaces.Event;
|
|
import Interfaces.EventObserver;
|
|
import javafx.util.Pair;
|
|
|
|
public class ApiCall implements Runnable, EventObserver {
|
|
|
|
//Methode appelée une fois que la requete s'est terminé
|
|
private Callback callback;
|
|
//connection HTTP
|
|
private HttpURLConnection connection;
|
|
//méthode HTTP
|
|
private String method;
|
|
//est ce que cet appel d'API attend un évenement pour se lancer
|
|
private Boolean isDelayed = false;
|
|
//Methode appellée une fois l'évenement arrivé, il retourne la nouvelle URL et les nouveaux parametres POST
|
|
private DelayedCallback delayedCallback;
|
|
//ID et Type de l'évenement attendu
|
|
private String eventID;
|
|
private String eventType;
|
|
//objet contenant le thread de l'appel
|
|
private Thread thread;
|
|
//si une erreur surviens durant le delayedCallback, la boucle run doit tout arreter, cette variable sert a notifier run() de ça
|
|
private Boolean shouldStop = false;
|
|
|
|
|
|
public ApiCall(String URL, String method, Callback call) {
|
|
this.callback = call;
|
|
this.method = method;
|
|
try {
|
|
//création de la connection
|
|
URL url = new URL(URL);
|
|
this.connection = (HttpURLConnection) url.openConnection();
|
|
this.connection.setRequestMethod(method);
|
|
//si on fait une requete GET, il faut interdire l'envoie de donnée POST
|
|
if(method == "GET") {
|
|
this.connection.setDoOutput(false);
|
|
}else {
|
|
this.connection.setDoOutput(true);
|
|
}
|
|
} catch (IOException e) {
|
|
this.callback.onError();
|
|
}
|
|
}
|
|
|
|
public void addHeaders(HashMap<String,String> map) {
|
|
Iterator it = map.entrySet().iterator();
|
|
while (it.hasNext()) {
|
|
Map.Entry pair = (Map.Entry)it.next();
|
|
this.connection.setRequestProperty((String)pair.getKey(), (String)pair.getValue());
|
|
it.remove(); // évite les erreurs en cas de modification concurente
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
//si notre appel est delayed, on endort le thread
|
|
if(this.isDelayed) {
|
|
try {
|
|
//on doit se synchroniser avec le thread avant de l'endormir
|
|
synchronized(this.thread) {
|
|
this.thread.wait();
|
|
}
|
|
} catch (InterruptedException e) {
|
|
this.callback.onError();
|
|
return;
|
|
}
|
|
}
|
|
|
|
//si il y a eu une erreur durant le delayedallback, on stope le thread
|
|
if(this.shouldStop) {
|
|
return;
|
|
}
|
|
try {
|
|
//On envoie les paramètres POST si besoin
|
|
if(this.method != "GET") {
|
|
DataOutputStream wr = new DataOutputStream (connection.getOutputStream ());
|
|
//TODO: implémenter la gestion des parametres POST
|
|
wr.flush ();
|
|
wr.close ();
|
|
}
|
|
|
|
//on récupère la réponse de la requete
|
|
InputStream is = connection.getInputStream();
|
|
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
|
|
String line;
|
|
StringBuffer response = new StringBuffer();
|
|
while((line = rd.readLine()) != null) {
|
|
response.append(line);
|
|
}
|
|
rd.close();
|
|
|
|
//transformation en objet JSON
|
|
try {
|
|
//raplce null values by empty strings
|
|
JSONObject json = new JSONObject(response.toString().replaceAll(":null,", ":\"\","));
|
|
this.callback.onSuccess(json);
|
|
}catch(JSONException e) {
|
|
this.callback.onError();
|
|
}
|
|
|
|
} catch (IOException e) {
|
|
this.callback.onError();
|
|
}
|
|
}
|
|
|
|
public void send() {
|
|
//send sert juste a lancer la boucle principale run()
|
|
this.thread = new Thread(this);
|
|
this.thread.start();
|
|
}
|
|
|
|
public void setAsDelayedCall(String eventID, String eventType, DelayedCallback call) {
|
|
//on enregistre tout ce dont on a besoin pour traiter l'évenement
|
|
this.isDelayed = true;
|
|
this.delayedCallback = call;
|
|
this.eventID = eventID;
|
|
this.eventType = eventType;
|
|
}
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
//si on est un appel delayed et que l'évenement est le bon, on lance le delayedCallback
|
|
if(this.isDelayed && e.getObjectId() == this.eventID && e.getEventType() == this.eventType) {
|
|
Pair<String,HashMap<String,String>> returned = this.delayedCallback.call();
|
|
if(this.method == "GET") {
|
|
try {
|
|
//on met a jour la connection HTTP avec la nouvelle URL en gardant l'ancienne méthode HTTP
|
|
HttpURLConnection newConnection = (HttpURLConnection) new URL(returned.getKey()).openConnection();
|
|
newConnection.setRequestMethod(this.connection.getRequestMethod());
|
|
newConnection.setDoOutput(this.connection.getDoOutput());
|
|
this.connection = newConnection;
|
|
//on a fini de mettre a jour la connection, le thread principal peut reprendre
|
|
synchronized(this.thread) {
|
|
this.thread.notify();
|
|
}
|
|
} catch (IOException e1) {
|
|
//une erreur est survenue, on stope tout
|
|
this.callback.onError();
|
|
this.shouldStop = true;
|
|
synchronized(this.thread) {
|
|
this.thread.notify();
|
|
}
|
|
}
|
|
}else {
|
|
//TODO: implémenter les param POST
|
|
}
|
|
}else {
|
|
this.callback.onError();
|
|
this.shouldStop = true;
|
|
synchronized(this.thread) {
|
|
this.thread.notify();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|