/* 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.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import de.uhilger.mediaz.App; import static de.uhilger.mediaz.App.RB_EP_LISTE; 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.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 Verwaltung von Entitaeten der Mediazentrale * * @author Ulrich Hilger * @version 1, 5.4.2021 */ public class StorageHandler extends AbstractHandler implements HttpHandler { private static final Logger logger = Logger.getLogger(StorageHandler.class.getName()); /* PUT Die angegebene Ressource wird angelegt. Wenn die Ressource bereits existiert, wird sie geändert. Das REST-Muster sieht je Entitaet fuenf Faelle vor (Beispiel Ablageort): 1. HTTP GET Ablageort/[Name] - Liefere den Ablageort namens [Name] als JSON 2. HTTP GET Ablageort/liste/ - Liefere eine Liste mit Namen aller Ablageorte Es duerfen also keine Elemente namens "liste" angelegt werden 3. HTTP GET Ablageort/ - Liefere eine Liste aller Ablageort-Objekte als JSON 4. HTTP PUT Ablageort/[Name] - Die angegebene Ressource wird angelegt. Wenn die Ressource bereits existiert, wird sie geändert. 5. HTTP DELETE - loesche den Ablageort falsch: 1. HTTP GET Ablageort/[Name] - Liefere den Ablageort namens [Name] als JSON 2. HTTP GET Ablageort/liste/ - Liefere eine Liste mit Namen aller Ablageorte 2. HTTP GET Ablageort/ - Liefere eine Liste aller Ablageort-Objekte 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 alle Ablageort-Objekte HTTP GET an /mz/api/store/Ablageort/liste/ liefert eine Liste der Namen vorhandener Ablageorte HTTP GET an /mz/api/store/Ablageort/[Name] liest den Ablageort namens [Name] HTTP PUT an /mz/api/store/Ablageort/[Name] wenn [Name] existiert: Aenderung, sonst neu anlegen HTTP DELETE an /mz/api/store/Ablageort/[Name] löscht den Ablageort namens [Name] */ /** 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"; public static final String EP_LISTE = "liste/"; @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 = put(e); break; case HTTP_POST: response = "nicht unterstuertzt."; code = 404; break; case HTTP_DELETE: boolean geloescht = loeschen(e); if(geloescht) { response = "geloescht"; } else { response = "nicht geloescht"; } break; } logger.fine(response); e.sendResponseHeaders(code, response.length()); OutputStream os = e.getResponseBody(); os.write(response.getBytes()); os.close(); } private String put(HttpExchange e) throws IOException { 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]; // alter Name, wenn Aenderung if(!elemName.equalsIgnoreCase(App.getRs(RB_EP_LISTE))) { FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF))); Gson gson = new Gson(); logger.log(Level.FINE, "type: {0}, token: {1}", new Object[]{type, fs.typeFromName(type).getType().getTypeName()}); Object o = gson.fromJson(bodyLesen(e), fs.typeFromName(type).getType()); if(o instanceof Entity) { Entity entity = (Entity) o; if(fs.exists(type, elemName)) { fs.delete(type, elemName); fs.write(entity, true); } else { fs.write(entity, false); } return type + App.getRs(Server.RB_SLASH) + entity.getName(); } else { return "Ungueltiges Objekt im Body."; } } else { return "Ungueltiger Elementname: " + App.getRs(RB_EP_LISTE); } } /* private String schreiben(FileStorage fs, String typ, String name, String body, boolean overwrite) { Gson gson = new Gson(); logger.log(Level.FINE, "type: {0}, token: {1}", new Object[]{typ, fs.typeFromName(typ).getType().getTypeName()}); Object o = gson.fromJson(body, fs.typeFromName(typ).getType()); if(o instanceof Entity) { Object antwortObjekt = fs.write((Entity) o, overwrite); if(antwortObjekt instanceof File) { File file = (File) antwortObjekt; logger.log(Level.FINE, "Datei {0} geschrieben.", file.getAbsolutePath()); String filename = file.getName(); return typ + FileHandler.STR_BLANK + filename; } } return typ + FileHandler.STR_BLANK + " etwas Seltsames ist passiert."; } */ /* private String neu(HttpExchange e) throws IOException { return schreiben(e, false); } private String aendern(HttpExchange e) throws IOException { return schreiben(e, true); } */ /* private String schreiben(HttpExchange e, boolean overwrite) 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.FINE, "type: {0}, token: {1}", new Object[]{type, fs.typeFromName(type).getType().getTypeName()}); Object o = gson.fromJson(body, fs.typeFromName(type).getType()); if(o instanceof Entity) { Object antwortObjekt = fs.write((Entity) o, overwrite); if(antwortObjekt instanceof File) { File file = (File) antwortObjekt; logger.log(Level.FINE, "Datei {0} geschrieben.", file.getAbsolutePath()); filename = file.getName(); return type + FileHandler.STR_BLANK + filename; } } return type + FileHandler.STR_BLANK + " Operation 'neu' fuer bereits existierende Entitaet."; } */ /* 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))) { List list = null; if(elems[elems.length - 1].equalsIgnoreCase(App.getRs(RB_EP_LISTE))) { String type = elems[elems.length - 2]; logger.fine(type); list = fs.list(type); } else { String type = elems[elems.length - 1]; logger.fine(type); list = fs.listObjects(type); } return jsonWithEnclosingType(list); } else { String type = elems[elems.length - 2]; String elemName = elems[elems.length - 1]; return fs.readJson(type, elemName); } } 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.FINE, "json: {0}", json); return json; } }