/* Mediazentrale - Personal Media Center Copyright (C) 2021 Ulrich Hilger This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package de.uhilger.mediaz.api; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import de.uhilger.mediaz.App; import de.uhilger.mediaz.Server; import static de.uhilger.mediaz.Server.RB_SLASH; import de.uhilger.mediaz.store.FileStorage; import de.uhilger.mediaz.entity.Entity; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * HttpHandler fuer die Ablage von Entitaeten der Mediazentrale * * @author Ulrich Hilger * @version 1, 5.4.2021 */ public class StorageHandler implements HttpHandler { private static final Logger logger = Logger.getLogger(StorageHandler.class.getName()); /* Das REST-Muster sieht je Entitaet fuenf Faelle vor (Beispiel Ablageort): 1. HTTP GET Ablageort/[Name]: Liefere den Ablageort als JSON 2. HTTP GET Ablageort/: Liefere einer Liste von Ablageorten als JSON 3. HTTP PUT: schreibe einen neuen Ablageort auf die Platte 4. HTTP POST: schreibe Aenderungen auf die Platte 5. HTTP DELETE: loesche den Ablageort Beispiele: HTTP GET an /mz/api/store/Ablageort/ liefert eine Liste der Namen vorhandener Ablageorte HTTP GET an /mz/api/store/Ablageort/Katalog liest den Ablageort namens "Katalog" HTTP POST an /mz/api/store/Ablageort schreibt den neuen Ablageort im Body der Anfrage (Neu) HTTP PUT an /mz/api/store/Ablageort sucht den Ablageort mit dem Namen laut Body der Anfrage und schreibt den Inhalt aus der Anfrage in die Datei (Aenderung) HTTP DELETE an /mz/api/store/Ablageort/Katalog löscht den Ablageort namens "Katalog" */ /** Name der HTTP Methode GET */ public static final String HTTP_GET = "GET"; /** Name der HTTP Methode PUT */ public static final String HTTP_PUT = "PUT"; /** Name der HTTP Methode POST */ public static final String HTTP_POST = "POST"; /** Name der HTTP Methode DELETE */ public static final String HTTP_DELETE = "DELETE"; @Override public void handle(HttpExchange e) throws IOException { String method = e.getRequestMethod(); String response = ""; int code = 200; switch(method) { case HTTP_GET: String json = lesen(e); if(json != null) { response = json; } else { response = "nicht gefunden"; code = 404; } break; case HTTP_PUT: response = aendern(e); break; case HTTP_POST: response = neu(e); break; case HTTP_DELETE: boolean geloescht = loeschen(e); if(geloescht) { response = "geloescht"; } else { response = "nicht geloescht"; } break; } logger.info(response); e.sendResponseHeaders(code, response.length()); OutputStream os = e.getResponseBody(); os.write(response.getBytes()); os.close(); } private String neu(HttpExchange e) throws IOException { String path = e.getRequestURI().toString(); String[] elems = path.split(App.getRs(Server.RB_SLASH)); String type = elems[elems.length - 1]; String body = bodyLesen(e); String filename = ""; FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF))); Gson gson = new Gson(); logger.log(Level.INFO, "type: {0}", type); Object o = gson.fromJson(body, fs.typeFromName(type).getType()); if(o instanceof Entity) { Object antwortObjekt = fs.write((Entity) o); if(antwortObjekt instanceof File) { File file = (File) antwortObjekt; logger.log(Level.INFO, "Datei {0} geschrieben.", file.getAbsolutePath()); filename = file.getName(); } } return type + FileHandler.STR_BLANK + filename; } private String aendern(HttpExchange e) throws IOException { return neu(e); // einstweilen wird einfach ueberschrieben } private boolean loeschen(HttpExchange e) { String path = e.getRequestURI().toString(); String[] elems = path.split(App.getRs(Server.RB_SLASH)); String type = elems[elems.length - 2]; String elemName = elems[elems.length - 1]; FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF))); return fs.delete(type, elemName); } private String lesen(HttpExchange e) { String path = e.getRequestURI().toString(); String[] elems = path.split(App.getRs(Server.RB_SLASH)); FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF))); if(path.endsWith(App.getRs(RB_SLASH))) { String type = elems[elems.length - 1]; logger.info(type); List list = fs.list(type); return jsonWithEnclosingType(list); } else { String type = elems[elems.length - 2]; String elemName = elems[elems.length - 1]; return fs.readJson(type, elemName); } } private String jsonWithEnclosingType(Object o) { StringBuilder sb = new StringBuilder(); sb.append("{\""); sb.append(o.getClass().getSimpleName()); sb.append("\": "); Gson gson = new Gson(); sb.append(gson.toJson(o)); sb.append("}"); return sb.toString(); } private String bodyLesen(HttpExchange e) throws IOException { InputStream is = e.getRequestBody(); BufferedReader r = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = r.readLine(); while(line != null) { sb.append(line); line = r.readLine(); } r.close(); String json = sb.toString(); logger.log(Level.INFO, "json: {0}", json); return json; } }