Persoenliche Mediazentrale
ulrich
2021-04-06 bebd4767df2dd419a2d04eaa4253592d13336e8c
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;
24 import de.uhilger.mediaz.Server;
2b5c60 25 import static de.uhilger.mediaz.Server.RB_SLASH;
081606 26 import de.uhilger.mediaz.store.FileStorage;
b1bf96 27 import de.uhilger.mediaz.entity.Entity;
b379f5 28 import java.io.BufferedReader;
081606 29 import java.io.File;
b379f5 30 import java.io.IOException;
U 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   /*
2b5c60 50     Das REST-Muster sieht je Entitaet fuenf Faelle vor (Beispiel Ablageort):
U 51     
52     1. HTTP GET Ablageort/[Name]: Liefere den Ablageort als JSON
53     2. HTTP GET Ablageort/: Liefere einer Liste von Ablageorten als JSON
54     3. HTTP PUT: schreibe einen neuen Ablageort auf die Platte
55     4. HTTP POST: schreibe Aenderungen auf die Platte
56     5. HTTP DELETE: loesche den Ablageort
b379f5 57   
U 58     Beispiele:
2b5c60 59   
U 60     HTTP GET an /mz/api/store/Ablageort/
61     liefert eine Liste der Namen vorhandener Ablageorte
b379f5 62   
U 63     HTTP GET an /mz/api/store/Ablageort/Katalog
64     liest den Ablageort namens "Katalog"
65   
66     HTTP POST an /mz/api/store/Ablageort
081606 67     schreibt den neuen Ablageort im Body der Anfrage (Neu)
b379f5 68   
U 69     HTTP PUT an /mz/api/store/Ablageort
70     sucht den Ablageort mit dem Namen laut Body der Anfrage 
081606 71     und schreibt den Inhalt aus der Anfrage in die Datei (Aenderung)
b379f5 72   
U 73     HTTP DELETE an /mz/api/store/Ablageort/Katalog
74     löscht den Ablageort namens "Katalog"
75   
76   */
77   
2b5c60 78   /** Name der HTTP Methode GET */
b379f5 79   public static final String HTTP_GET = "GET";
2b5c60 80   
U 81   /** Name der HTTP Methode PUT */
b379f5 82   public static final String HTTP_PUT = "PUT";
2b5c60 83   
U 84   /** Name der HTTP Methode POST */
b379f5 85   public static final String HTTP_POST = "POST";
2b5c60 86   
U 87   /** Name der HTTP Methode DELETE */
b379f5 88   public static final String HTTP_DELETE = "DELETE";
U 89
90   @Override
91   public void handle(HttpExchange e) throws IOException {
92     String method = e.getRequestMethod();
5f70da 93     String response = "";
U 94     int code = 200;
b379f5 95     switch(method) {
U 96       case HTTP_GET:
5f70da 97         String json = lesen(e);
U 98         if(json != null) {
99           response = json;
100         } else {
101           response = "nicht gefunden";
102           code = 404;
103         }
b379f5 104         break;
U 105         
106       case HTTP_PUT:
2b5c60 107         response = aendern(e);
b379f5 108         break;
U 109         
110       case HTTP_POST:
5f70da 111         response = neu(e);
b379f5 112         break;
U 113         
114       case HTTP_DELETE:
2b5c60 115         boolean geloescht = loeschen(e);
U 116         if(geloescht) {
117           response = "geloescht";
118         } else {
119           response = "nicht geloescht";
120         }
b379f5 121         break;
U 122     }
b29119 123     logger.fine(response);
5f70da 124     e.sendResponseHeaders(code, response.length());
b379f5 125     OutputStream os = e.getResponseBody();
U 126     os.write(response.getBytes());
127     os.close();        
b1bf96 128   }
U 129   
5f70da 130   private String neu(HttpExchange e) throws IOException {
2597cd 131     return schreiben(e, false);
U 132   }
133   
134   private String aendern(HttpExchange e) throws IOException {
135     return schreiben(e, true);
136   }
137   
138   private String schreiben(HttpExchange e, boolean overwrite) throws IOException {
b1bf96 139     String path = e.getRequestURI().toString();
U 140     String[] elems = path.split(App.getRs(Server.RB_SLASH));
141     String type = elems[elems.length - 1];
142     String body = bodyLesen(e);
5f70da 143     String filename = ""; 
b1bf96 144     FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF)));
U 145     Gson gson = new Gson();
b29119 146     logger.log(Level.FINE, "type: {0}", type);
b1bf96 147     Object o = gson.fromJson(body, fs.typeFromName(type).getType());
U 148     if(o instanceof Entity) {
2597cd 149       Object antwortObjekt = fs.write((Entity) o, overwrite);
b1bf96 150       if(antwortObjekt instanceof File) {
U 151         File file = (File) antwortObjekt;
b29119 152         logger.log(Level.FINE, "Datei {0} geschrieben.", file.getAbsolutePath());
5f70da 153         filename = file.getName();
2597cd 154         return type + FileHandler.STR_BLANK + filename;
b1bf96 155       }
U 156     }
2597cd 157     return type + FileHandler.STR_BLANK + " Operation 'neu' fuer bereits existierende Entitaet.";
b1bf96 158   }
U 159   
2597cd 160   /*
2b5c60 161   private String aendern(HttpExchange e) throws IOException {
U 162     return neu(e); // einstweilen wird einfach ueberschrieben
b1bf96 163   }
2597cd 164   */
b1bf96 165   
2b5c60 166   private boolean loeschen(HttpExchange e) {
5f70da 167     String path = e.getRequestURI().toString();
U 168     String[] elems = path.split(App.getRs(Server.RB_SLASH));
169     String type = elems[elems.length - 2];
170     String elemName = elems[elems.length - 1];
171     FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF)));
2b5c60 172     return fs.delete(type, elemName);
U 173   }
174   
175   private String lesen(HttpExchange e) {
176     String path = e.getRequestURI().toString();
177     String[] elems = path.split(App.getRs(Server.RB_SLASH));
178     FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF)));
179     if(path.endsWith(App.getRs(RB_SLASH))) {
180       String type = elems[elems.length - 1];
b29119 181       logger.fine(type);
2b5c60 182       List list = fs.list(type);
a43e1a 183       return jsonWithEnclosingType(list);
2b5c60 184     } else {
U 185       String type = elems[elems.length - 2];
186       String elemName = elems[elems.length - 1];
187       return fs.readJson(type, elemName);
188     }
a43e1a 189   }
b379f5 190   
U 191   private String bodyLesen(HttpExchange e) throws IOException {
192     InputStream is = e.getRequestBody();
193     BufferedReader r = new BufferedReader(new InputStreamReader(is));
194     StringBuilder sb = new StringBuilder();
195     String line = r.readLine();
196     while(line != null) {
197       sb.append(line);
198       line = r.readLine();
199     }
200     r.close();
201     String json = sb.toString();
b29119 202     logger.log(Level.FINE, "json: {0}", json);
b379f5 203     return json;
U 204   }
205 }