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 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> 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(); } } } }