Dateien verwalten mit Modul jdk.httpserver
ulrich
2024-01-15 342aebc6b1143ab81a626a71b8bf7ce15eb5f361
Zentrale Methode mit Dateioperationen von FileMAnager nach Writer ausgelagert.
1 files modified
1 files added
414 ■■■■ changed files
src/de/uhilger/httpserver/cm/FileManager.java 203 ●●●●● patch | view | raw | blame | history
src/de/uhilger/httpserver/cm/actor/Writer.java 211 ●●●●● patch | view | raw | blame | history
src/de/uhilger/httpserver/cm/FileManager.java
@@ -17,40 +17,15 @@
 */
package de.uhilger.httpserver.cm;
import de.uhilger.httpserver.cm.actor.Zipper;
import de.uhilger.httpserver.cm.actor.Eraser;
import de.uhilger.httpserver.cm.actor.Unzipper;
import de.uhilger.httpserver.cm.actor.Renamer;
import com.google.gson.Gson;
import com.sun.net.httpserver.Authenticator;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import de.uhilger.httpserver.base.HttpResponder;
import de.uhilger.httpserver.base.HttpHelper;
import de.uhilger.httpserver.base.handler.FileHandler;
import de.uhilger.httpserver.cm.actor.Lister;
import de.uhilger.httpserver.cm.actor.Mover;
import de.uhilger.httpserver.image.Datei;
import de.uhilger.httpserver.image.ImageActor;
import de.uhilger.httpserver.image.ImageThread;
import de.uhilger.httpserver.image.ImageThread.ThreadListener;
import de.uhilger.httpserver.cm.actor.Writer;
import de.uhilger.httpserver.oauth.BearerAuthenticator;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import java.util.logging.Level;
/**
 * <p>Der FileManager verknuepft einen HTTP-Endpunkt mit einem Ordner des lokalen
@@ -130,15 +105,6 @@
  
  public static final String ATTR_ROLE = "role";
  
  //private String role;
  //public FileManager(String absoluteDirectoryPathAndName, String role, String ctx) {
  public FileManager() {
    //super(absoluteDirectoryPathAndName, ctx);
    //super(absoluteDirectoryPathAndName);
    //this.role = role;
  }
  @Override
  public void handle(HttpExchange e) throws IOException {
    Authenticator a = e.getHttpContext().getAuthenticator();
@@ -171,184 +137,27 @@
            }
            break;
          case HttpHelper.HTTP_PUT:
            put(e, helper);
            new Writer().put(e, helper);
            break;
          case HttpHelper.HTTP_POST:
            speichern(e, helper);
            new Writer().speichern(e, helper);
            break;
          case HttpHelper.HTTP_DELETE:
            loeschen(e, helper);
            new Writer().loeschen(e, helper);
            break;
        }
      } else {
        standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
        new Writer().standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
      }
    } else {
      standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
      new Writer().standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
    }
  }
  private void put(HttpExchange exchange, HttpHelper helper) throws IOException {
    String query = exchange.getRequestURI().getQuery();
    if (query != null) {
      String[] params = query.split("=");
      for (String param : params) {
        //logger.fine("param: " + param);
      }
      switch (params[0]) {
        case P_COPY:
          copyOrMove(exchange, params[1], helper.getFileName(exchange), OP_COPY);
          break;
        case P_MOVE:
          copyOrMove(exchange, params[1], helper.getFileName(exchange), OP_MOVE);
          break;
        case P_DUPLICATE:
          if(Boolean.parseBoolean(params[1])) {
            String neuerDateiName = new Mover().duplizieren(
                    exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(),
                    helper.getFileName(exchange));
            //logger.fine("neuer Name: " + neuerDateiName);
            standardHeaderUndAntwort(exchange, SC_OK, neuerDateiName);
          }
          break;
        case P_RENAME:
          String neuerDateiName = new Renamer().umbenennen(exchange, helper, params[1]);
          //logger.fine("neuer Name: " + neuerDateiName);
          standardHeaderUndAntwort(exchange, SC_OK, neuerDateiName);
          break;
        case P_ZIP:
          String path = exchange.getRequestURI().toString();
          //logger.fine(path);
          String antwort = new Zipper().packFolder(helper.getFileName(exchange), path, exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
          if(antwort.equalsIgnoreCase("ok")) {
            standardHeaderUndAntwort(exchange, SC_OK, antwort);
          } else {
            standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
          }
          break;
        case P_UNZIP:
          path = exchange.getRequestURI().toString();
          //logger.fine(path);
          antwort = new Unzipper().extractZipfile(helper.getFileName(exchange), path, exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
          if(antwort.equalsIgnoreCase("ok")) {
            standardHeaderUndAntwort(exchange, SC_OK, antwort);
          } else {
            standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
          }
          break;
      }
    } else {
      speichern(exchange, helper);
    }
  }
  
  private void emptyListResponse(HttpExchange e) throws IOException {
    HttpResponder r = new HttpResponder();
    String json = "{}";
    //logger.log(Level.FINE, "json: ''{0}''", json);
    r.antwortSenden(e, SC_OK, json);        
  }
  private void speichern(HttpExchange exchange, HttpHelper helper) throws IOException {
    String fileName = helper.getFileName(exchange);
    //logger.info("fileName: " + fileName);
    // file ist die Datei, um die es geht
    File file = new File(exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fileName);
    String method = exchange.getRequestMethod();
    if (fileName.endsWith(STR_SLASH)) {
      //logger.info("neuer Ordner: " + file.getAbsolutePath());
      // neuen Ordner erstellen oder ablehnen, wenn der Ordner schon existiert
      if (method.equalsIgnoreCase(HttpHelper.HTTP_POST)) {
        if (!file.exists()) {
          file.mkdir();
          standardHeaderUndAntwort(exchange, SC_OK, file.getAbsolutePath());
        } else {
          String antwort = "Ordner existiert bereits.";
          standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
        }
      } else {
        String antwort = "PUT fuer neuen Ordner nicht erlaubt, bitte POST verwenden.";
        standardHeaderUndAntwort(exchange, SC_METHOD_NOT_ALLOWED, antwort);
      }
    } else {
      //logger.info("Datei speichern: " + file.getAbsolutePath());
      // Datei speichern
      if (method.equalsIgnoreCase(HttpHelper.HTTP_POST)) {
        if (file.exists()) {
          FileTransporter trans = new FileTransporter();
          file = trans.getNewFileName(file);
        }
      } else if (method.equalsIgnoreCase(HttpHelper.HTTP_PUT)) {
        if (file.exists()) {
          /*
            muss delete() sein?
            pruefen: ueberschreibt der FileWriter den alteen Inhalt oder
            entsteht eine unerwuenschte Mischung aus altem und neuem
            Inhalt?
           */
          file.delete();
        } else {
          file.getParentFile().mkdirs();
        }
      }
      // Request Body mit dem Dateiinhalt in einen String lesen
      StringBuilder sb = new StringBuilder();
      InputStream is = exchange.getRequestBody();
      BufferedReader in = new BufferedReader(new InputStreamReader(is));
      String line = in.readLine();
      while (line != null) {
        sb.append(line);
        line = in.readLine();
      }
      // dekodieren
      String content = sb.toString();
      //logger.fine(content);
      String decoded = URLDecoder.decode(content, UTF8);
      //logger.fine(decoded);
      // in Datei schreiben
      byte[] bytes = decoded.getBytes();
      file.createNewFile();
      OutputStream os = new FileOutputStream(file);
      os.write(bytes);
      os.flush();
      os.close();
      is.close();
      // Antwort senden
      standardHeaderUndAntwort(exchange, SC_OK, file.getAbsolutePath());
    }
  }
  private void copyOrMove(HttpExchange exchange, String quelle, String ziel, int op) throws IOException {
    //logger.fine("quelle: " + quelle + ", ziel: " + ziel);
    String[] dateiNamen = dateiliste(exchange);
    new Mover().copyOrMoveFiles(quelle, ziel, dateiNamen, op, exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
    standardHeaderUndAntwort(exchange, SC_OK, "Dateien verarbeitet.");
  }
  private void loeschen(HttpExchange exchange, HttpHelper helper) throws IOException {
    String[] dateiNamen = dateiliste(exchange);
    String relPfad = helper.getFileName(exchange);
    new Eraser().deleteFiles(relPfad, Arrays.asList(dateiNamen), exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
    standardHeaderUndAntwort(exchange, SC_OK, "Dateien geloescht.");
  }
  private String[] dateiliste(HttpExchange exchange) throws IOException {
    String body = new HttpHelper().bodyLesen(exchange);
    //logger.fine("dateien: " + body);
    Gson gson = new Gson();
    return gson.fromJson(body, String[].class);
  }
  private void standardHeaderUndAntwort(HttpExchange exchange, int status, String antwort) throws IOException {
    Headers resHeaders = exchange.getResponseHeaders();
    resHeaders.add(CONTENT_TYPE, HttpHelper.CT_TEXT_HTML);
    new HttpResponder().antwortSenden(exchange, status, antwort);
  }  
}
src/de/uhilger/httpserver/cm/actor/Writer.java
New file
@@ -0,0 +1,211 @@
/*
  http-cm - File management extensions to jdk.httpserver
  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.httpserver.cm.actor;
import com.google.gson.Gson;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import de.uhilger.httpserver.base.HttpHelper;
import de.uhilger.httpserver.base.HttpResponder;
import de.uhilger.httpserver.base.handler.FileHandler;
import static de.uhilger.httpserver.base.handler.FileHandler.CONTENT_TYPE;
import static de.uhilger.httpserver.base.handler.FileHandler.SC_METHOD_NOT_ALLOWED;
import static de.uhilger.httpserver.base.handler.FileHandler.SC_OK;
import static de.uhilger.httpserver.base.handler.FileHandler.SC_UNPROCESSABLE_ENTITY;
import static de.uhilger.httpserver.cm.FileManager.OP_COPY;
import static de.uhilger.httpserver.cm.FileManager.OP_MOVE;
import static de.uhilger.httpserver.cm.FileManager.P_COPY;
import static de.uhilger.httpserver.cm.FileManager.P_DUPLICATE;
import static de.uhilger.httpserver.cm.FileManager.P_MOVE;
import static de.uhilger.httpserver.cm.FileManager.P_RENAME;
import static de.uhilger.httpserver.cm.FileManager.P_UNZIP;
import static de.uhilger.httpserver.cm.FileManager.P_ZIP;
import static de.uhilger.httpserver.cm.FileManager.STR_SLASH;
import static de.uhilger.httpserver.cm.FileManager.UTF8;
import de.uhilger.httpserver.cm.FileTransporter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.Arrays;
/**
 * Klasse mit Methoden zu schreibenden Dateioperationen
 *
 * @author Ulrich Hilger, 15. Janauar 2024
 */
public class Writer {
  public void put(HttpExchange exchange, HttpHelper helper) throws IOException {
    String query = exchange.getRequestURI().getQuery();
    if (query != null) {
      String[] params = query.split("=");
      for (String param : params) {
        //logger.fine("param: " + param);
      }
      switch (params[0]) {
        case P_COPY:
          copyOrMove(exchange, params[1], helper.getFileName(exchange), OP_COPY);
          break;
        case P_MOVE:
          copyOrMove(exchange, params[1], helper.getFileName(exchange), OP_MOVE);
          break;
        case P_DUPLICATE:
          if(Boolean.parseBoolean(params[1])) {
            String neuerDateiName = new Mover().duplizieren(
                    exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(),
                    helper.getFileName(exchange));
            //logger.fine("neuer Name: " + neuerDateiName);
            standardHeaderUndAntwort(exchange, SC_OK, neuerDateiName);
          }
          break;
        case P_RENAME:
          String neuerDateiName = new Renamer().umbenennen(exchange, helper, params[1]);
          //logger.fine("neuer Name: " + neuerDateiName);
          standardHeaderUndAntwort(exchange, SC_OK, neuerDateiName);
          break;
        case P_ZIP:
          String path = exchange.getRequestURI().toString();
          //logger.fine(path);
          String antwort = new Zipper().packFolder(helper.getFileName(exchange), path, exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
          if(antwort.equalsIgnoreCase("ok")) {
            standardHeaderUndAntwort(exchange, SC_OK, antwort);
          } else {
            standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
          }
          break;
        case P_UNZIP:
          path = exchange.getRequestURI().toString();
          //logger.fine(path);
          antwort = new Unzipper().extractZipfile(helper.getFileName(exchange), path, exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
          if(antwort.equalsIgnoreCase("ok")) {
            standardHeaderUndAntwort(exchange, SC_OK, antwort);
          } else {
            standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
          }
          break;
      }
    } else {
      speichern(exchange, helper);
    }
  }
  private void copyOrMove(HttpExchange exchange, String quelle, String ziel, int op) throws IOException {
    //logger.fine("quelle: " + quelle + ", ziel: " + ziel);
    String[] dateiNamen = dateiliste(exchange);
    new Mover().copyOrMoveFiles(quelle, ziel, dateiNamen, op, exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
    standardHeaderUndAntwort(exchange, SC_OK, "Dateien verarbeitet.");
  }
  public void loeschen(HttpExchange exchange, HttpHelper helper) throws IOException {
    String[] dateiNamen = dateiliste(exchange);
    String relPfad = helper.getFileName(exchange);
    new Eraser().deleteFiles(relPfad, Arrays.asList(dateiNamen), exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
    standardHeaderUndAntwort(exchange, SC_OK, "Dateien geloescht.");
  }
  private String[] dateiliste(HttpExchange exchange) throws IOException {
    String body = new HttpHelper().bodyLesen(exchange);
    //logger.fine("dateien: " + body);
    Gson gson = new Gson();
    return gson.fromJson(body, String[].class);
  }
  public void standardHeaderUndAntwort(HttpExchange exchange, int status, String antwort) throws IOException {
    Headers resHeaders = exchange.getResponseHeaders();
    resHeaders.add(CONTENT_TYPE, HttpHelper.CT_TEXT_HTML);
    new HttpResponder().antwortSenden(exchange, status, antwort);
  }
  public void speichern(HttpExchange exchange, HttpHelper helper) throws IOException {
    String fileName = helper.getFileName(exchange);
    //logger.info("fileName: " + fileName);
    // file ist die Datei, um die es geht
    File file = new File(exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fileName);
    String method = exchange.getRequestMethod();
    if (fileName.endsWith(STR_SLASH)) {
      //logger.info("neuer Ordner: " + file.getAbsolutePath());
      // neuen Ordner erstellen oder ablehnen, wenn der Ordner schon existiert
      if (method.equalsIgnoreCase(HttpHelper.HTTP_POST)) {
        if (!file.exists()) {
          file.mkdir();
          new Writer().standardHeaderUndAntwort(exchange, SC_OK, file.getAbsolutePath());
        } else {
          String antwort = "Ordner existiert bereits.";
          new Writer().standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
        }
      } else {
        String antwort = "PUT fuer neuen Ordner nicht erlaubt, bitte POST verwenden.";
        new Writer().standardHeaderUndAntwort(exchange, SC_METHOD_NOT_ALLOWED, antwort);
      }
    } else {
      //logger.info("Datei speichern: " + file.getAbsolutePath());
      // Datei speichern
      if (method.equalsIgnoreCase(HttpHelper.HTTP_POST)) {
        if (file.exists()) {
          FileTransporter trans = new FileTransporter();
          file = trans.getNewFileName(file);
        }
      } else if (method.equalsIgnoreCase(HttpHelper.HTTP_PUT)) {
        if (file.exists()) {
          /*
            muss delete() sein?
            pruefen: ueberschreibt der FileWriter den alteen Inhalt oder
            entsteht eine unerwuenschte Mischung aus altem und neuem
            Inhalt?
           */
          file.delete();
        } else {
          file.getParentFile().mkdirs();
        }
      }
      // Request Body mit dem Dateiinhalt in einen String lesen
      StringBuilder sb = new StringBuilder();
      InputStream is = exchange.getRequestBody();
      BufferedReader in = new BufferedReader(new InputStreamReader(is));
      String line = in.readLine();
      while (line != null) {
        sb.append(line);
        line = in.readLine();
      }
      // dekodieren
      String content = sb.toString();
      //logger.fine(content);
      String decoded = URLDecoder.decode(content, UTF8);
      //logger.fine(decoded);
      // in Datei schreiben
      byte[] bytes = decoded.getBytes();
      file.createNewFile();
      OutputStream os = new FileOutputStream(file);
      os.write(bytes);
      os.flush();
      os.close();
      is.close();
      // Antwort senden
      standardHeaderUndAntwort(exchange, SC_OK, file.getAbsolutePath());
    }
  }
}