Dateiverwaltung für die WebBox
ulrich
2017-03-31 6e70be4f54f3482801d579407846810926cd9997
wbx-lib ausgebaut
3 files modified
3 files added
583 ■■■■■ changed files
src/java/de/uhilger/filecms/api/Api.java 88 ●●●●● patch | view | raw | blame | history
src/java/de/uhilger/filecms/api/FileMgr.java 4 ●●●● patch | view | raw | blame | history
src/java/de/uhilger/filecms/data/Bild.java 181 ●●●●● patch | view | raw | blame | history
src/java/de/uhilger/filecms/data/FileRef.java 206 ●●●●● patch | view | raw | blame | history
src/java/de/uhilger/filecms/web/Initialiser.java 101 ●●●●● patch | view | raw | blame | history
src/java/de/uhilger/filecms/web/UploadServlet.java 3 ●●●● patch | view | raw | blame | history
src/java/de/uhilger/filecms/api/Api.java
@@ -20,19 +20,25 @@
package de.uhilger.filecms.api;
import de.uhilger.filecms.data.FileRef;
import de.uhilger.filecms.web.Initialiser;
import de.uhilger.transit.web.RequestKontext;
import de.uhilger.transit.web.WebKontext;
import de.uhilger.wbx.api.ApiBase;
import de.uhilger.wbx.data.FileRef;
import java.io.File;
import java.security.Principal;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
/**
 *
 */
public abstract class Api extends ApiBase implements WebKontext {
public abstract class Api implements WebKontext, RequestKontext {
  
  protected ServletContext ctx;  
  /** Zeiger zum Request, der zur Ausfuehrung fuehrte */
  protected HttpServletRequest request;
  
  private static final Logger logger = Logger.getLogger(Api.class.getName());
@@ -107,6 +113,70 @@
    }
    return base;
  }
  /* -------------- Hilfsfunktionen --------------- */
  /**
   * Das Datenverzeichnis der WebBox ermitteln
   * @return Ordner $wbx/daten
   */
  protected File getFileBase(ServletContext ctx) {
    File file = null;
    Object o = ctx.getAttribute(Initialiser.FILE_BASE);
    if(o instanceof String) {
      String baseStr = (String) o;
      logger.fine(baseStr);
      file = new File(baseStr);
    }
    return file;
  }
  /**
   * Den absoluten Pfad zum Verzeichnis ermitteln das gemaess der
   * Tomcat-Doku als CATALINA_BASE der WebBox gilt
   * @return absoluter Pfad zu $wbx/sys/base
   */
  protected String getCatalinaBase(ServletContext ctx) {
    String path = ctx.getRealPath("/");
    logger.fine("getRealPath: " + path); // file-cms in webapps
    File file = new File(path);
    file = file.getParentFile().getParentFile();
    return file.getAbsolutePath();
  }
  /**
   * Den absoluten Pfad zum Datenverzeichnis der WebBox ermitteln
   * @return absoluter Pfad zu $wbx/daten
   */
  protected String getWbxDataDir(ServletContext ctx) {
    return getFileBase(ctx).getAbsolutePath();
  }
  /**
   * Das Verzeichnis ermitteln, in dem die WebBox laeuft
   * @return der Ordner $wbx
   */
  protected File getWbxDir(ServletContext ctx) {
    String path = ctx.getRealPath("/");
    logger.fine("getRealPath: " + path);
    File file = new File(path);
    file = file.getParentFile().getParentFile().getParentFile().getParentFile();
    logger.fine("WebBox: " + file.getAbsolutePath());
    return file;
  }
  /**
   * den Namen des angemeldeten Benutzers ermitteln
   * @return Name des angemeldeten Benutzers oder null, wenn keiner angemeldet ist
   */
  protected String getUserName() {
    String userName = null;
    Object p = getRequest().getUserPrincipal();
    if(p instanceof Principal) {
      userName = ((Principal) p).getName();
    }
    return userName;
  }
  
  /* ------------- Implementierung WebKontext ------------- */
@@ -121,4 +191,16 @@
    this.ctx = servletContext;
  }
  
  /* ------------- Implementierung RequestKontext ------------- */
  @Override
  public HttpServletRequest getRequest() {
    return request;
  }
  @Override
  public void setRequest(HttpServletRequest r) {
    this.request = r;
  }
}
src/java/de/uhilger/filecms/api/FileMgr.java
@@ -18,8 +18,8 @@
package de.uhilger.filecms.api;
import de.uhilger.wbx.Bild;
import de.uhilger.wbx.data.FileRef;
import de.uhilger.filecms.data.Bild;
import de.uhilger.filecms.data.FileRef;
import java.awt.Container;
import java.awt.Image;
import java.awt.MediaTracker;
src/java/de/uhilger/filecms/data/Bild.java
New file
@@ -0,0 +1,181 @@
/*
    Dateiverwaltung - File management in your browser
    Copyright (C) 2017 Ulrich Hilger, http://uhilger.de
    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 <http://www.gnu.org/licenses/>.
*/
package de.uhilger.filecms.data;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.FileNameMap;
import java.net.URLConnection;
import javax.imageio.ImageIO;
/**
 * Methoden zur Verkleinerung von Bildern
 */
public class Bild {
  public static final int WINZIG = 0;
  public static final int KLEIN = 1;
  public static final int MITTEL = 2;
  public static final int GROSS = 3;
  public static final String[] GRNAME = {"-w", "-k", "-m", "-g"};
  public static final int[] GR = {120, 240, 700, 1200};
  public void writeImageStream(Image image, int gr, String mimeType, OutputStream out) throws InterruptedException, IOException {
    ImageIO.write(getReducedImage(image, gr, mimeType), imgType(mimeType), out);
  }
  /**
   *
   * @param image
   * @param gr
   * @param mimeType
   * @param vName Name der verkleinerten Datei
   * @throws InterruptedException
   * @throws IOException
   */
  public void writeImageFile(Image image, int gr, String mimeType, String vName) throws InterruptedException, IOException {
    ImageIO.write(getReducedImage(image, gr, mimeType), imgType(mimeType), new File(vName));
  }
  private BufferedImage getReducedImage(Image image, int gr, String mimeType) throws InterruptedException, IOException {
    BufferedImage img;
    int q = 90;
    float sh = 0.f;
    if(mimeType.contains("jpeg")) {
      img = getReducedImage(image, gr, gr, q, sh, false);
    } else {
      img = getReducedImage(image, gr, gr, q, sh, true);
    }
    return img;
  }
  /**
   * Eine in Groesse und Qualitaet verringerte Bilddatei erzeugen
   * @param image  Ablageort und Name der Bilddatei
   * @param width  neue Breite
   * @param height  neue hoehe
   * @param quality neue Qualitaet (0 - 100)
   * @param factor Faktor fuer Schaerfe / Unschaerfe (z.B. -0.15f fuer leichte Unschaerfe, 0.05f fuer leichtes Nachschaerfen)
   * @param withTransparency ob Transparenz benoetigt wird
   * @return neues, in Groesse und Qualitaet entsprechend verringertes Bild
   * @throws java.lang.InterruptedException
   * @throws java.io.FileNotFoundException
   */
  public BufferedImage getReducedImage(Image image, int width, int height, int quality, float factor, boolean withTransparency)
  throws InterruptedException, FileNotFoundException, IOException {
    int imageWidth = image.getWidth(null);
        int imageHeight = image.getHeight(null);
      int thumbWidth = width;
        int thumbHeight = height;
    if(imageWidth < width) {
      thumbWidth = imageWidth;
    }
    if(imageHeight < height) {
      thumbHeight = imageHeight;
    }
        double thumbRatio = (double)thumbWidth / (double)thumbHeight;
        double imageRatio = (double)imageWidth / (double)imageHeight;
        if (thumbRatio < imageRatio) {
            thumbHeight = (int)(thumbWidth / imageRatio);
        }
        else {
            thumbWidth = (int)(thumbHeight * imageRatio);
        }
        // draw original image to thumbnail image object and
        // scale it to the new size on-the-fly
        //BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB);
    BufferedImage thumbImage;
    if(withTransparency) {
        thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_ARGB);
    } else {
      thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB);
    }
        Graphics2D graphics2D = thumbImage.createGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
        // 30.7.2007: sharpening hinzugefuegt (Anfang)
        //float factor = -0.15f; // minus = sharpen, plus = soften
        //float[] sharpenArray = {0, -1, 0, -1, 5, -1, 0, -1, 0};
    /*
      30.6.2013: sharpening als Weichmacher nur, wenn Bild < 400
    */
    /*if(thumbWidth < 400 || thumbHeight < 400) {
      factor = 0.1f;
    }*/
        if(factor != 0.f) {
            float[] array = {0, factor, 0, factor, 1-(factor*4), factor, 0, factor, 0};
            Kernel kernel = new Kernel(3, 3, array);
            ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
            thumbImage = cOp.filter(thumbImage, null);
        }
        // 30.7.2007: sharpening hinzugefuegt (Ende)
    return thumbImage;
  }
  public String imgType(String mimeType) {
    String imgType;
    if(mimeType.contains("jpg")) {
      imgType = "jpg";
    } else if(mimeType.contains("jpeg")) {
      imgType = "jpg";
    } else if(mimeType.contains("png")) {
      imgType = "png";
    } else if(mimeType.contains("gif")) {
      imgType = "gif";
    } else {
      imgType = "jpg";
    }
    return imgType;
  }
  /**
   *
   * @param v Bild.WINZIG .. Bild.GROSS
   * @return L&auml;nge der l&auml;ngsten Kante in Bildpunkten
   */
  public int getVariantenGroesse(int v) {
    return GR[v];
  }
  public String getVariantenName(int v) {
    return GRNAME[v];
  }
  public String getMimeType(File file) {
    String absName = file.getAbsolutePath();
    FileNameMap fileNameMap = URLConnection.getFileNameMap();
    return fileNameMap.getContentTypeFor("file://" + absName);
  }
}
src/java/de/uhilger/filecms/data/FileRef.java
New file
@@ -0,0 +1,206 @@
/*
    WebBox - Dein Server.
    Copyright (C) 2017 Ulrich Hilger, http://uhilger.de
    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 <http://www.gnu.org/licenses/>.
 */
package de.uhilger.filecms.data;
import java.io.Serializable;
/**
 * A reference to a file consisting of the file's absolute path and additional
 * information about whether or not the referenced file is a directory, is hidden, etc.
 * Note that FileRef only references a file, the file itself and its contents are not
 * modelled by this class.
 *
 * @author Ulrich Hilger, http://uhilger.de
 * @author Bereitgestellt unter den Bedingungen der
 *  <a href="http://www.gnu.org/licenses/agpl-3.0" target="_blank">GNU Affero
 *  General Public License</a>
 *
 * @version 2, 12.01.2008
 */
public class FileRef implements Serializable {
  public static final long serialVersionUID = 42L;
  private String absolutePath;
    private Boolean isDirectory;
    private Boolean isHidden;
    private Long lastModified;
    private Long length;
  private String mimetype;
    /**
     * create a new instance of <code>FileRef</code>. Note that the created FileRef is
     * only a reference to a file, the file itself will not be created.
     *
     * @param absolutePath  the absolute path that denotes this instance of <code>FileRef</code>
     * @param isDirectory  whether or not this file is a directory
     * @param isHidden  whether or not this file is a hidden file
     * @param lastModified  the date/time this file was last modified measured in milliseconds
     *                         since the epoch (00:00:00 GMT, January 1, 1970)
     * @param length the length of this file in bytes
     */
    public FileRef(String absolutePath, boolean isDirectory, boolean isHidden,
            long lastModified, long length)
    {
        super();
        this.absolutePath = absolutePath;
        this.isDirectory = isDirectory;
        this.isHidden = isHidden;
        this.lastModified = lastModified;
        this.length = length;
    }
    /**
     * Create a new instance of class <code>FileRef</code> with a given absolute path.
     * Other characteristics of the file are created with default settings
     * (i.e. not a directory, not hidden, unknown modification date
     * and length). Note that the created FileRef is only a reference to a file, the file
     * itself will not be created.
     *
     * @param absolutePath  the absolute path that denotes this instance
     * of <code>FileRef</code>
     */
    public FileRef(String absolutePath) {
        this(absolutePath, false, false, 0, 0);
    }
    /**
     * Create a new instance of class <code>FileRef</code> with a given absolute path
     * and an indicator whether or not the new FileRef denotes a directory.
     * Other characteristics of the file are created with default settings
     * (i.e. not hidden, unknown modification date and length). Note that the created
     * FileRef is only a reference to a file, the file itself will not be created.
     *
     * @param absolutePath  the absolute path that denotes this instance
     * of <code>FileRef</code>
     * @param isDirectory  true, if the file to create should denote a directory
     */
    public FileRef(String absolutePath, boolean isDirectory) {
        this(absolutePath, isDirectory, false, 0, 0);
    }
  public String getMimetype() {
    return mimetype;
  }
  public void setMimetype(String mimetype) {
    this.mimetype = mimetype;
  }
    /**
     * get the absolute path that denotes this file
     * @return  the path
     */
    public String getAbsolutePath() {
        return absolutePath;
    }
    /**
     * Tests whether the file denoted by this abstract pathname is a
     * directory.
     *
     * @return <code>true</code> if this file is a directory,
     *          <code>false</code> otherwise
     */
    public boolean isDirectory() {
        return isDirectory;
    }
    /**
     * Tests whether the file denoted by this abstract pathname is a
     * file.
     *
     * @return <code>true</code> if this file is a file,
     *          <code>false</code> otherwise
     */
    public boolean isFile() {
        return !isDirectory;
    }
    /**
     * Tests whether the file denoted by this abstract pathname is a
     * hidden file.
     *
     * @return <code>true</code> if this file is a hidden file,
     *          <code>false</code> otherwise
     */
    public boolean isHidden() {
        return isHidden;
    }
    /**
     * Returns the time that this file was
     * last modified.
     *
     * @return  A <code>long</code> value representing the time the file was
     *          last modified, measured in milliseconds since the epoch
     *          (00:00:00 GMT, January 1, 1970)
     */
    public long getLastModified() {
        return lastModified;
    }
    /**
     * Returns the length of this file.
     * The return value is unspecified if this file denotes a directory.
     *
     * @return  The length, in bytes, of this file
     */
    public long getLength() {
        return length;
    }
    /**
     * get the name of this file without path
     * @param separatorChar  the string that is used to separate directories and file names in
     * path expressions
     * @return the name of this file without path
     */
    public String getName(String separatorChar) {
        String path = getAbsolutePath();
        String name = path.substring(path.lastIndexOf(separatorChar) + 1);
        if(name == null || name.length() < 1) {
            name = path;
        }
        return name;
    }
    /**
     * get a string representation of this instance of FileRef
     * @return the string representation of this FileRef object
     */
    public String toString() {
        return getAbsolutePath();
    }
    /**
     * Indicates whether some object is equal to this instance of class FileRef. Two
     * GenericFiles are regarded as equal when their absolute paths are equal case independently.
     *
     * @param  obj  the object to compare with this instance of FileRef
     * @return true, if obj is equal to this instance of FileRef, false if not
     */
    public boolean equals(Object obj) {
        boolean isEqual = false;
        if(obj != null && obj instanceof FileRef) {
            isEqual = ((FileRef) obj).getAbsolutePath().toLowerCase().equals(
                    this.getAbsolutePath().toLowerCase());
        }
        return isEqual;
    }
}
src/java/de/uhilger/filecms/web/Initialiser.java
New file
@@ -0,0 +1,101 @@
/*
    Dateiverwaltung - File management in your browser
    Copyright (C) 2017 Ulrich Hilger, http://uhilger.de
    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 <http://www.gnu.org/licenses/>.
*/
package de.uhilger.filecms.web;
import java.io.File;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
/**
 * Initialisieren der Dateiverwaltung
 */
public class Initialiser {
  private static final Logger logger = Logger.getLogger(Initialiser.class.getName());
  public static final String FILE_BASE = "filebase";
  public static final String DATENABLAGE = "datenAblage";
  /**
   * Bei der WebBox ist das Datenverzeichnis relativ zum Verzeichnis
   * $CATALINA_BASE/webapps untergebracht.
   * Die Abfrage ServletContext.getRealPath
   * liefert das Verzeichnis des Context dieser Webanwendung, also
   * $CATALINA_BASE/webapps/file-cms
   * oder
   * $WBX/sys/base/webapps/file-cms
   *
   * Unter Windows z.B.
   * C:\Users\fred\Documents\srv\wbx\sys\base\webapps\file-cms
   * Unter Linux oder Mac OS z.B.
   * /home/fred/srv/wbx/sys/base/webapps/file-cms
   *
   * Das Datenverzeichis liegt dann auf
   * $WBX/daten
   *
   * Mit dem Verzeichnis des Context dieser Webanwendung ist das
   * Datenverzeichnis der WebBox hart kodierbar mit dieser Methode
   *
   * @return Verzeichnis 'daten' der WebBox
   */
  protected File getWbxDataDir(ServletContext ctx) {
    File file = getWbxDir(ctx);
    file = new File(file, "daten/");
    logger.fine("WebBox Datenbasis: " + file.getAbsolutePath());
    return file;
  }
  protected File getWbxDir(ServletContext ctx) {
    String path = ctx.getRealPath("/");
    logger.fine("getRealPath: " + path); // file-cms in webapps
    File file = new File(path);
    file = file.getParentFile().getParentFile().getParentFile().getParentFile();
    logger.fine("WebBox: " + file.getAbsolutePath());
    return file;
  }
  /**
   * Die Dateiablage wird entweder auf einen absoluten Pfad gesetzt,
   * der im Deployment Descriptor hinterlegt werden kann oder, wenn
   * dort nichts eingetragen ist, auf den hart kodierten Pfad
   * der WebBox.
   *
   * @param ctx der ServletContext, in den die Angabe eingetragen wird. Dort
   * ist anschliessend die Angabe unter Initialiser.FILE_BASE abrufbar
   */
  protected void ablageErmitteln(ServletContext ctx) {
    Object o = ctx.getInitParameter(DATENABLAGE);
    try {
      if(o instanceof String) {
        String pfad = o.toString();
        if(pfad.trim().length() > 0) {
          ctx.setAttribute(FILE_BASE, pfad);
          logger.fine("Basis: " + pfad);
        } else {
          ctx.setAttribute(FILE_BASE, getWbxDataDir(ctx).getAbsolutePath());
        }
      } else {
        ctx.setAttribute(FILE_BASE, getWbxDataDir(ctx).getAbsolutePath());
      }
    } catch(Exception ex) {
      ctx.setAttribute(FILE_BASE, getWbxDataDir(ctx).getAbsolutePath());
    }
  }
}
src/java/de/uhilger/filecms/web/UploadServlet.java
@@ -22,8 +22,7 @@
import static de.uhilger.filecms.api.FileMgr.HOME_DIR_PATH;
import static de.uhilger.filecms.api.FileMgr.PUB_DIR_NAME;
import static de.uhilger.filecms.api.FileMgr.PUB_DIR_PATH;
import de.uhilger.wbx.data.FileRef;
import de.uhilger.wbx.web.Initialiser;
import de.uhilger.filecms.data.FileRef;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;