From dfb7d34f88efbb3eb7632ae628ccfd4576824477 Mon Sep 17 00:00:00 2001 From: ulrich Date: Thu, 08 Apr 2021 10:37:10 +0000 Subject: [PATCH] REST-Konformitaet des StorageHandler verbessert --- src/de/uhilger/mediaz/api/StorageHandler.java | 98 +++++++++++++++--- src/de/uhilger/mediaz/store/FileStorage.java | 4 src/de/uhilger/mediaz/entity/Titel.java | 44 ++++++++ src/de/uhilger/mediaz/store/Storage.java | 2 src/mediaz_de_DE.properties | 2 src/de/uhilger/mediaz/Server.java | 22 +-- www/ui/js/app.js | 36 ++++--- src/de/uhilger/mediaz/entity/Abspielliste.java | 48 +++++++++ 8 files changed, 207 insertions(+), 49 deletions(-) diff --git a/src/de/uhilger/mediaz/Server.java b/src/de/uhilger/mediaz/Server.java index 68a0ce4..3cad81f 100644 --- a/src/de/uhilger/mediaz/Server.java +++ b/src/de/uhilger/mediaz/Server.java @@ -104,23 +104,18 @@ String wwwData = App.getInitParameter(App.getRs(App.RB_AP_WWW_DATA)); File wwwDir = new File(wwwData); - //String ui = App.getInitParameter(App.getRs(App.RB_AP_UI)); - //File uiDir = new File(ui); HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); - server.createContext(ctx + App.getRs(RB_WEBROOT), - new FileHandler(wwwDir.getAbsolutePath())); + server.createContext(ctx + App.getRs(RB_WEBROOT), new FileHandler(wwwDir.getAbsolutePath())); ablageorteEinklinken(server); server.createContext(ctx + App.getRs(RB_STORE), new StorageHandler()); - //server.createContext(ctx + App.getRs(RB_UI_ROOT), new FileHandler(uiDir.getAbsolutePath())); server.createContext(ctx + App.getRs(RB_STOP_SERVER), new StopServerHandler()); - //server.createContext(ctx + App.getRs(RB_ABLAGE_TEST), new AblageTestHandler()); - //server.createContext(ctx + App.getRs(RB_STORE_TEST), new StoreTestHandler()); server.setExecutor(Executors.newFixedThreadPool(20)); server.start(); } - private void ablageorteEinklinken(HttpServer server) throws ClassNotFoundException, IOException { + private void ablageorteEinklinken(HttpServer server) + throws ClassNotFoundException, IOException { String typ = Ablageort.class.getSimpleName(); FileStorage store = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF))); List<String> orte = store.list(typ); @@ -129,12 +124,11 @@ String ortName = i.next(); Entity e = store.read(typ, ortName); if(e instanceof Ablageort) { - Ablageort ort = (Ablageort) e; - Ablageort ablageort = (Ablageort) e; - logger.fine(ctx + ablageort.getUrl()); - logger.fine(ablageort.getOrt()); - server.createContext(ctx + ablageort.getUrl(), - new ListFileHandler(new File(ablageort.getOrt()).getAbsolutePath())); + Ablageort ablageort = (Ablageort) e; + logger.log(Level.FINE, "{0}{1}", new Object[]{ctx, ablageort.getUrl()}); + logger.fine(ablageort.getOrt()); + server.createContext(ctx + ablageort.getUrl(), + new ListFileHandler(new File(ablageort.getOrt()).getAbsolutePath())); } } } diff --git a/src/de/uhilger/mediaz/api/StorageHandler.java b/src/de/uhilger/mediaz/api/StorageHandler.java index 3b8e010..255380f 100644 --- a/src/de/uhilger/mediaz/api/StorageHandler.java +++ b/src/de/uhilger/mediaz/api/StorageHandler.java @@ -27,7 +27,6 @@ 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; @@ -48,13 +47,29 @@ /* + + 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 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 + 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: @@ -64,18 +79,14 @@ HTTP GET an /mz/api/store/Ablageort/liste/ liefert eine Liste der Namen vorhandener Ablageorte - HTTP GET an /mz/api/store/Ablageort/Katalog - liest den Ablageort namens "Katalog" + HTTP GET an /mz/api/store/Ablageort/[Name] + liest den Ablageort namens [Name] - HTTP POST an /mz/api/store/Ablageort - schreibt den neuen Ablageort im Body der Anfrage (Neu) + HTTP PUT an /mz/api/store/Ablageort/[Name] + wenn [Name] existiert: Aenderung, sonst neu anlegen - 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" + HTTP DELETE an /mz/api/store/Ablageort/[Name] + löscht den Ablageort namens [Name] */ @@ -110,11 +121,12 @@ break; case HTTP_PUT: - response = aendern(e); + response = put(e); break; case HTTP_POST: - response = neu(e); + response = "nicht unterstuertzt."; + code = 404; break; case HTTP_DELETE: @@ -133,6 +145,51 @@ 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); } @@ -140,7 +197,9 @@ 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)); @@ -162,6 +221,7 @@ } return type + FileHandler.STR_BLANK + " Operation 'neu' fuer bereits existierende Entitaet."; } + */ /* private String aendern(HttpExchange e) throws IOException { @@ -184,7 +244,7 @@ FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF))); if(path.endsWith(App.getRs(RB_SLASH))) { List list = null; - if(path.endsWith(App.getRs(RB_EP_LISTE))) { + if(elems[elems.length - 1].equalsIgnoreCase(App.getRs(RB_EP_LISTE))) { String type = elems[elems.length - 2]; logger.fine(type); list = fs.list(type); diff --git a/src/de/uhilger/mediaz/entity/Abspielliste.java b/src/de/uhilger/mediaz/entity/Abspielliste.java new file mode 100644 index 0000000..0f6ef6f --- /dev/null +++ b/src/de/uhilger/mediaz/entity/Abspielliste.java @@ -0,0 +1,48 @@ +/* + 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 <https://www.gnu.org/licenses/>. + */ +package de.uhilger.mediaz.entity; + +import java.util.List; + +/** + * + * @author ulrich + */ +public class Abspielliste implements Entity { + + private String name; + private List<Titel> titel; + + public List<Titel> getTitel() { + return titel; + } + + public void setTitel(List titel) { + this.titel = titel; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/src/de/uhilger/mediaz/entity/Titel.java b/src/de/uhilger/mediaz/entity/Titel.java new file mode 100644 index 0000000..51fb606 --- /dev/null +++ b/src/de/uhilger/mediaz/entity/Titel.java @@ -0,0 +1,44 @@ +/* + 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 <https://www.gnu.org/licenses/>. + */ +package de.uhilger.mediaz.entity; + +/** + * + * @author ulrich + */ +public class Titel { + private String katalogUrl; + private String name; + + public String getKatalogUrl() { + return katalogUrl; + } + + public void setKatalogUrl(String katalogUrl) { + this.katalogUrl = katalogUrl; + } + + public String getName() { + return name; + } + + public void setName(String titel) { + this.name = titel; + } + +} diff --git a/src/de/uhilger/mediaz/store/FileStorage.java b/src/de/uhilger/mediaz/store/FileStorage.java index 217420c..b9f5df8 100644 --- a/src/de/uhilger/mediaz/store/FileStorage.java +++ b/src/de/uhilger/mediaz/store/FileStorage.java @@ -218,4 +218,8 @@ return list; } + public boolean exists(String typ, String name) { + return getFile(typ, name).exists(); + } + } diff --git a/src/de/uhilger/mediaz/store/Storage.java b/src/de/uhilger/mediaz/store/Storage.java index 7a1803e..3f63bc8 100644 --- a/src/de/uhilger/mediaz/store/Storage.java +++ b/src/de/uhilger/mediaz/store/Storage.java @@ -102,4 +102,6 @@ * @return true, wenn geloeschn, false wenn nicht */ public boolean delete(String typ, String name); + + public boolean exists(String typ, String name); } diff --git a/src/mediaz_de_DE.properties b/src/mediaz_de_DE.properties index bc25054..63a69fc 100644 --- a/src/mediaz_de_DE.properties +++ b/src/mediaz_de_DE.properties @@ -10,7 +10,7 @@ webroot=/ # uiroot=/ui store=/api/store -epliste=liste/ +epliste=liste stopServer=/api/server/stop testAblage=/api/test/ablage testStore=/api/test/store diff --git a/www/ui/js/app.js b/www/ui/js/app.js index ded0e0e..02cf400 100644 --- a/www/ui/js/app.js +++ b/www/ui/js/app.js @@ -193,19 +193,22 @@ document.querySelector('#abspieler-url').value ); var daten = JSON.stringify(abspieler); - if(typeof pl === "undefined" || pl.key !== plname) { + //if(typeof pl === "undefined" || pl.key !== plname) { + if(typeof pl.name === "undefined" || pl.name.length < 1) { // neu - self.http_post('../api/store/Abspieler', daten, function (responseText) { + self.http_put('../api/store/Abspieler/' + plname, daten, function (responseText) { // hier die Antwort verarbeiten + self.abspieler_auswahl_fuellen(); + self.abspieler_liste(); }); } else { // aendern - self.http_put('../api/store/Abspieler', daten, function (responseText) { + self.http_put('../api/store/Abspieler/' + pl.name, daten, function (responseText) { // hier die Antwort verarbeiten + self.abspieler_auswahl_fuellen(); + self.abspieler_liste(); }); } - //document.querySelector(".zentraler-inhalt").innerHTML = ''; - self.abspieler_liste(); }); self.addEvtListener('#cancel-btn', 'click', function () { //document.querySelector(".zentraler-inhalt").innerHTML = ''; @@ -221,6 +224,7 @@ // hier die Antwort verarbeiten self.dialog_schliessen(); //document.querySelector(".zentraler-inhalt").innerHTML = ''; + self.abspieler_auswahl_fuellen(); self.abspieler_liste(); }); }); @@ -240,19 +244,20 @@ document.querySelector('#einstellung-value').value ); var daten = JSON.stringify(pref); - if(typeof k === "undefined" || k.key !== pkey) { + //if(typeof k === "undefined" || k.key !== pkey) { + if(typeof k.key === "undefined" || k.key.length < 1) { // neu - self.http_post('../api/store/Einstellung', daten, function (responseText) { + self.http_put('../api/store/Einstellung/' + pkey, daten, function (responseText) { // hier die Antwort verarbeiten + self.prefs_liste(); }); } else { // aendern - self.http_put('../api/store/Einstellung', daten, function (responseText) { + self.http_put('../api/store/Einstellung/' + k.key, daten, function (responseText) { // hier die Antwort verarbeiten + self.prefs_liste(); }); } - //document.querySelector(".zentraler-inhalt").innerHTML = ''; - self.prefs_liste(); }); self.addEvtListener('#cancel-btn', 'click', function () { //document.querySelector(".zentraler-inhalt").innerHTML = ''; @@ -296,19 +301,20 @@ document.querySelector('#ablageort-url').value ); var daten = JSON.stringify(a); - if(typeof ort === "undefined" || ort.name !== aName) { + //if(typeof ort === "undefined" || ort.name !== aName) { + if(typeof ort.name === "undefined" || ort.name.length < 1) { // neu - self.http_post('../api/store/Ablageort', daten, function (responseText) { + self.http_put('../api/store/Ablageort/' + aName, daten, function (responseText) { // hier die Antwort verarbeiten + self.ablageort_liste(); }); } else { // aendern - self.http_put('../api/store/Ablageort', daten, function (responseText) { + self.http_put('../api/store/Ablageort/' + ort.name, daten, function (responseText) { // hier die Antwort verarbeiten + self.ablageort_liste(); }); } - //document.querySelector(".zentraler-inhalt").innerHTML = ''; - self.ablageort_liste(); }); self.addEvtListener('#cancel-btn', 'click', function () { //document.querySelector(".zentraler-inhalt").innerHTML = ''; -- Gitblit v1.9.3