Persoenliche Mediazentrale
ulrich
2021-04-08 dfb7d34f88efbb3eb7632ae628ccfd4576824477
commit | author | age
b379f5 1 /*
5f70da 2   Mediazentrale - Personal Media Center
U 3   Copyright (C) 2021  Ulrich Hilger
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU Affero General Public License as
7   published by the Free Software Foundation, either version 3 of the
8   License, or (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU Affero General Public License for more details.
14
15   You should have received a copy of the GNU Affero General Public License
16   along with this program.  If not, see <https://www.gnu.org/licenses/>.
b379f5 17  */
U 18 package de.uhilger.mediaz.api;
19
20 import com.google.gson.Gson;
21 import com.sun.net.httpserver.HttpExchange;
22 import com.sun.net.httpserver.HttpHandler;
23 import de.uhilger.mediaz.App;
f45e20 24 import static de.uhilger.mediaz.App.RB_EP_LISTE;
b379f5 25 import de.uhilger.mediaz.Server;
2b5c60 26 import static de.uhilger.mediaz.Server.RB_SLASH;
081606 27 import de.uhilger.mediaz.store.FileStorage;
b1bf96 28 import de.uhilger.mediaz.entity.Entity;
b379f5 29 import java.io.BufferedReader;
U 30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.InputStreamReader;
33 import java.io.OutputStream;
2b5c60 34 import java.util.List;
081606 35 import java.util.logging.Level;
b379f5 36 import java.util.logging.Logger;
U 37
38 /**
2597cd 39  * HttpHandler fuer die Verwaltung von Entitaeten der Mediazentrale
5f70da 40  * 
U 41  * @author Ulrich Hilger
42  * @version 1, 5.4.2021
b379f5 43  */
86bbf7 44 public class StorageHandler extends AbstractHandler implements HttpHandler {
b379f5 45   
081606 46   private static final Logger logger = Logger.getLogger(StorageHandler.class.getName());
b379f5 47
U 48   
49   /*
dfb7d3 50   
U 51     PUT Die angegebene Ressource wird angelegt. Wenn die Ressource bereits 
52            existiert, wird sie geändert. 
53   
2b5c60 54     Das REST-Muster sieht je Entitaet fuenf Faelle vor (Beispiel Ablageort):
U 55     
dfb7d3 56     1. HTTP GET Ablageort/[Name]  - Liefere den Ablageort namens [Name] als JSON
U 57     2. HTTP GET Ablageort/liste/  - Liefere eine Liste mit Namen aller Ablageorte
58                                      Es duerfen also keine Elemente namens "liste" angelegt werden
59     3. HTTP GET Ablageort/        - Liefere eine Liste aller Ablageort-Objekte als JSON
60     4. HTTP PUT Ablageort/[Name]  - Die angegebene Ressource wird angelegt. Wenn die Ressource 
61                                      bereits existiert, wird sie geändert. 
62     5. HTTP DELETE                - loesche den Ablageort
63     
64   
65   
66     falsch:
67     1. HTTP GET Ablageort/[Name]  - Liefere den Ablageort namens [Name] als JSON
68     2. HTTP GET Ablageort/liste/  - Liefere eine Liste mit Namen aller Ablageorte
69     2. HTTP GET Ablageort/  - Liefere eine Liste aller Ablageort-Objekte als JSON
70     3. HTTP PUT  - schreibe einen neuen Ablageort auf die Platte
71     4. HTTP POST  - schreibe Aenderungen auf die Platte
72     5. HTTP DELETE  - loesche den Ablageort
b379f5 73   
U 74     Beispiele:
2b5c60 75   
U 76     HTTP GET an /mz/api/store/Ablageort/
f45e20 77     liefert alle Ablageort-Objekte
U 78   
79     HTTP GET an /mz/api/store/Ablageort/liste/  
2b5c60 80     liefert eine Liste der Namen vorhandener Ablageorte
b379f5 81   
dfb7d3 82     HTTP GET an /mz/api/store/Ablageort/[Name]
U 83     liest den Ablageort namens [Name]
b379f5 84   
dfb7d3 85     HTTP PUT an /mz/api/store/Ablageort/[Name]
U 86     wenn [Name] existiert: Aenderung, sonst neu anlegen
b379f5 87   
dfb7d3 88     HTTP DELETE an /mz/api/store/Ablageort/[Name]
U 89     löscht den Ablageort namens [Name]
b379f5 90   
U 91   */
92   
2b5c60 93   /** Name der HTTP Methode GET */
b379f5 94   public static final String HTTP_GET = "GET";
2b5c60 95   
U 96   /** Name der HTTP Methode PUT */
b379f5 97   public static final String HTTP_PUT = "PUT";
2b5c60 98   
U 99   /** Name der HTTP Methode POST */
b379f5 100   public static final String HTTP_POST = "POST";
2b5c60 101   
U 102   /** Name der HTTP Methode DELETE */
b379f5 103   public static final String HTTP_DELETE = "DELETE";
f45e20 104   
U 105   public static final String EP_LISTE = "liste/";
b379f5 106
U 107   @Override
108   public void handle(HttpExchange e) throws IOException {
109     String method = e.getRequestMethod();
5f70da 110     String response = "";
U 111     int code = 200;
b379f5 112     switch(method) {
U 113       case HTTP_GET:
5f70da 114         String json = lesen(e);
U 115         if(json != null) {
116           response = json;
117         } else {
118           response = "nicht gefunden";
119           code = 404;
120         }
b379f5 121         break;
U 122         
123       case HTTP_PUT:
dfb7d3 124         response = put(e);
b379f5 125         break;
U 126         
127       case HTTP_POST:
dfb7d3 128         response = "nicht unterstuertzt.";
U 129         code = 404;
b379f5 130         break;
U 131         
132       case HTTP_DELETE:
2b5c60 133         boolean geloescht = loeschen(e);
U 134         if(geloescht) {
135           response = "geloescht";
136         } else {
137           response = "nicht geloescht";
138         }
b379f5 139         break;
U 140     }
b29119 141     logger.fine(response);
5f70da 142     e.sendResponseHeaders(code, response.length());
b379f5 143     OutputStream os = e.getResponseBody();
U 144     os.write(response.getBytes());
145     os.close();        
b1bf96 146   }
U 147   
dfb7d3 148   private String put(HttpExchange e) throws IOException {
U 149     String path = e.getRequestURI().toString();
150     String[] elems = path.split(App.getRs(Server.RB_SLASH));
151     String type = elems[elems.length - 2];
152     String elemName = elems[elems.length - 1]; // alter Name, wenn Aenderung
153     if(!elemName.equalsIgnoreCase(App.getRs(RB_EP_LISTE))) {
154       FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF)));
155       Gson gson = new Gson();
156       logger.log(Level.FINE, "type: {0}, token: {1}", new Object[]{type, fs.typeFromName(type).getType().getTypeName()});
157       Object o = gson.fromJson(bodyLesen(e), fs.typeFromName(type).getType());
158       if(o instanceof Entity) {
159         Entity entity = (Entity) o;
160         if(fs.exists(type, elemName)) {
161           fs.delete(type, elemName);
162           fs.write(entity, true);
163         } else {
164           fs.write(entity, false);
165         }
166         return type + App.getRs(Server.RB_SLASH) + entity.getName();
167       } else {
168         return "Ungueltiges Objekt im Body.";
169       }
170     } else {
171       return "Ungueltiger Elementname: " + App.getRs(RB_EP_LISTE);
172     }
173   }
174   
175   /*
176   private String schreiben(FileStorage fs, String typ, String name, String body, boolean overwrite) {
177     Gson gson = new Gson();
178     logger.log(Level.FINE, "type: {0}, token: {1}", new Object[]{typ, fs.typeFromName(typ).getType().getTypeName()});
179     Object o = gson.fromJson(body, fs.typeFromName(typ).getType());
180     if(o instanceof Entity) {
181       Object antwortObjekt = fs.write((Entity) o, overwrite);
182       if(antwortObjekt instanceof File) {
183         File file = (File) antwortObjekt;
184         logger.log(Level.FINE, "Datei {0} geschrieben.", file.getAbsolutePath());
185         String filename = file.getName();
186         return typ + FileHandler.STR_BLANK + filename;
187       }
188     }    
189     return typ + FileHandler.STR_BLANK + " etwas Seltsames ist passiert.";
190   }
191   */
192   /*
5f70da 193   private String neu(HttpExchange e) throws IOException {
2597cd 194     return schreiben(e, false);
U 195   }
196   
197   private String aendern(HttpExchange e) throws IOException {
198     return schreiben(e, true);
199   }
dfb7d3 200   */
2597cd 201   
dfb7d3 202   /*
2597cd 203   private String schreiben(HttpExchange e, boolean overwrite) throws IOException {
b1bf96 204     String path = e.getRequestURI().toString();
U 205     String[] elems = path.split(App.getRs(Server.RB_SLASH));
206     String type = elems[elems.length - 1];
207     String body = bodyLesen(e);
5f70da 208     String filename = ""; 
b1bf96 209     FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF)));
U 210     Gson gson = new Gson();
cf6509 211     logger.log(Level.FINE, "type: {0}, token: {1}", new Object[]{type, fs.typeFromName(type).getType().getTypeName()});
b1bf96 212     Object o = gson.fromJson(body, fs.typeFromName(type).getType());
U 213     if(o instanceof Entity) {
2597cd 214       Object antwortObjekt = fs.write((Entity) o, overwrite);
b1bf96 215       if(antwortObjekt instanceof File) {
U 216         File file = (File) antwortObjekt;
b29119 217         logger.log(Level.FINE, "Datei {0} geschrieben.", file.getAbsolutePath());
5f70da 218         filename = file.getName();
2597cd 219         return type + FileHandler.STR_BLANK + filename;
b1bf96 220       }
U 221     }
2597cd 222     return type + FileHandler.STR_BLANK + " Operation 'neu' fuer bereits existierende Entitaet.";
b1bf96 223   }
dfb7d3 224   */
b1bf96 225   
2597cd 226   /*
2b5c60 227   private String aendern(HttpExchange e) throws IOException {
U 228     return neu(e); // einstweilen wird einfach ueberschrieben
b1bf96 229   }
2597cd 230   */
b1bf96 231   
2b5c60 232   private boolean loeschen(HttpExchange e) {
5f70da 233     String path = e.getRequestURI().toString();
U 234     String[] elems = path.split(App.getRs(Server.RB_SLASH));
235     String type = elems[elems.length - 2];
236     String elemName = elems[elems.length - 1];
237     FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF)));
2b5c60 238     return fs.delete(type, elemName);
U 239   }
240   
241   private String lesen(HttpExchange e) {
242     String path = e.getRequestURI().toString();
243     String[] elems = path.split(App.getRs(Server.RB_SLASH));
244     FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF)));
245     if(path.endsWith(App.getRs(RB_SLASH))) {
f45e20 246       List list = null;
dfb7d3 247       if(elems[elems.length - 1].equalsIgnoreCase(App.getRs(RB_EP_LISTE))) {
f45e20 248         String type = elems[elems.length - 2];
U 249         logger.fine(type);
250         list = fs.list(type);
251       } else {
252         String type = elems[elems.length - 1];
253         logger.fine(type);
254         list = fs.listObjects(type);
255       }
a43e1a 256       return jsonWithEnclosingType(list);
2b5c60 257     } else {
U 258       String type = elems[elems.length - 2];
259       String elemName = elems[elems.length - 1];
260       return fs.readJson(type, elemName);
261     }
a43e1a 262   }
b379f5 263   
U 264   private String bodyLesen(HttpExchange e) throws IOException {
265     InputStream is = e.getRequestBody();
266     BufferedReader r = new BufferedReader(new InputStreamReader(is));
267     StringBuilder sb = new StringBuilder();
268     String line = r.readLine();
269     while(line != null) {
270       sb.append(line);
271       line = r.readLine();
272     }
273     r.close();
274     String json = sb.toString();
b29119 275     logger.log(Level.FINE, "json: {0}", json);
b379f5 276     return json;
U 277   }
278 }