com.ibm.xsp.webdav.WebDavManager.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.xsp.webdav.WebDavManager.java

Source

/** ========================================================================= *
 * Copyright (C) 2012 IBM Corporation                                         *
 *           based on work of                                                 *
 * Copyright (C) 2006, 2007 TAO Consulting Pte <http://www.taoconsulting.sg/> *
 *                            All rights reserved.                            *
 * ========================================================================== *
 *                                                                            *
 * Licensed under the  Apache License, Version 2.0  (the "License").  You may *
 * not use this file except in compliance with the License.  You may obtain a *
 * copy of the License at <http://www.apache.org/licenses/LICENSE-2.0>.       *
 *                                                                            *
 * Unless  required  by applicable  law or  agreed  to  in writing,  software *
 * distributed under the License is distributed on an  "AS IS" BASIS, WITHOUT *
 * WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied.  See the *
 * License for the  specific language  governing permissions  and limitations *
 * under the License.                                                         *
 *                                                                            *
 * ========================================================================== **/
package com.ibm.xsp.webdav;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import biz.taoconsulting.dominodav.LockManager;
import com.ibm.xsp.webdav.repository.DAVRepositoryMETA;

/**
 * The webDAV manager handles the webDAV configuration, the supported methods
 * and the potential webDAV methods, refactored out of the original servlet
 * Implemented as singleton
 * 
 * @author Stephan H. Wissel
 * 
 */
public class WebDavManager {

    /**
     * Key to load the supported HTTP methods like get, post etc.
     */
    private static final String SUPPORTEDMETHODSFILE = "methods.properties";

    /**
     * Properties of the Meta repository like the styles to use and where to
     * find the repositories
     */
    public static final String METAREPOPROPFILE = "metarepository.properties";

    /**
     * Key to load temp directory
     */
    private static final String INIT_KEY_TEMPDIR = "temp-directory";

    /**
     * The instance of the class we return
     */
    private static WebDavManager internalWebDavManager = null;

    /**
     * The logger object for event logging
     */
    private static final Log LOGGER = LogFactory.getLog(WebDavManager.class);

    private static final String DEFAULT_TMP_DIR = "/tmp";

    /**
     * Style for PROPFIND in XSLT
     */
    private String propfindStyle;

    /**
     * Style for PROPFIND in XSLT for the list of repositories
     */
    private String rootPropfindStyle;

    /**
     * tempDir the directory for temporary file operations
     */
    private String tempDir;

    /**
     * Can the manager been reset, should be false for production The property
     * doesn't prevent anything but the servlet is querying it
     */
    private boolean allowReset = true;

    /**
     * The path of the servlet, needs to prefix repositories and files
     */
    private String servletPath;

    /**
     * Mimetype registry
     */
    private HashMap<String, String> knownMimeTypes;

    /**
     * 
     * @return the servlet Path
     */
    public String getServletPath() {
        return servletPath;
    }

    /**
     * 
     * @param servletPath
     *            prefix for making repositories complete
     */
    public void setServletPath(String servletPath) {
        this.servletPath = servletPath;
    }

    /**
     * Should the Manager be resettable
     * 
     * @return
     */
    public boolean isAllowReset() {
        return allowReset;
    }

    /**
     * Initialize the Manager and make sure we did load everything
     */
    private synchronized static void initializeWebDavManager(String servletPath) {
        if (internalWebDavManager == null) {
            internalWebDavManager = new WebDavManager();
        }
        if (servletPath != null) {
            internalWebDavManager.setServletPath(servletPath);
        }
        internalWebDavManager.getLockManager(); // Start the lock manager
        internalWebDavManager.loadSupportedMethods(); // The maximum of methods
        // we currently support
        internalWebDavManager.loadMetaRepository(); // The repository of our
        // repositories
        internalWebDavManager.loadMimeTypes(); // All the mimetypes we know
    }

    private void loadMimeTypes() {
        // TODO Find a better way than hardcoding them here!
        this.knownMimeTypes = new HashMap<String, String>();
        this.knownMimeTypes.put("abs", "audio/x-mpeg");
        this.knownMimeTypes.put("ai", "application/postscript");
        this.knownMimeTypes.put("aif", "audio/x-aiff");
        this.knownMimeTypes.put("aifc", "audio/x-aiff");
        this.knownMimeTypes.put("aiff", "audio/x-aiff");
        this.knownMimeTypes.put("aim", "application/x-aim");
        this.knownMimeTypes.put("art", "image/x-jg");
        this.knownMimeTypes.put("asf", "video/x-ms-asf");
        this.knownMimeTypes.put("asx", "video/x-ms-asf");
        this.knownMimeTypes.put("au", "audio/basic");
        this.knownMimeTypes.put("avi", "video/x-msvideo");
        this.knownMimeTypes.put("avx", "video/x-rad-screenplay");
        this.knownMimeTypes.put("bcpio", "application/x-bcpio");
        this.knownMimeTypes.put("bin", "application/octet-stream");
        this.knownMimeTypes.put("bmp", "image/bmp");
        this.knownMimeTypes.put("body", "text/html");
        this.knownMimeTypes.put("cdf", "application/x-cdf");
        this.knownMimeTypes.put("cer", "application/x-x509-ca-cert");
        this.knownMimeTypes.put("class", "application/java");
        this.knownMimeTypes.put("cpio", "application/x-cpio");
        this.knownMimeTypes.put("csh", "application/x-csh");
        this.knownMimeTypes.put("css", "text/css");
        this.knownMimeTypes.put("dib", "image/bmp");
        this.knownMimeTypes.put("doc", "application/msword");
        this.knownMimeTypes.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        this.knownMimeTypes.put("dtd", "application/xml-dtd");
        this.knownMimeTypes.put("dv", "video/x-dv");
        this.knownMimeTypes.put("dvi", "application/x-dvi");
        this.knownMimeTypes.put("eps", "application/postscript");
        this.knownMimeTypes.put("etx", "text/x-setext");
        this.knownMimeTypes.put("exe", "application/octet-stream");
        this.knownMimeTypes.put("gif", "image/gif");
        this.knownMimeTypes.put("gtar", "application/x-gtar");
        this.knownMimeTypes.put("gz", "application/x-gzip");
        this.knownMimeTypes.put("hdf", "application/x-hdf");
        this.knownMimeTypes.put("hqx", "application/mac-binhex40");
        this.knownMimeTypes.put("htc", "text/x-component");
        this.knownMimeTypes.put("htm", "text/html");
        this.knownMimeTypes.put("html", "text/html");
        this.knownMimeTypes.put("hqx", "application/mac-binhex40");
        this.knownMimeTypes.put("ief", "image/ief");
        this.knownMimeTypes.put("ini", "text/plain");
        this.knownMimeTypes.put("jad", "text/vnd.sun.j2me.app-descriptor");
        this.knownMimeTypes.put("jar", "application/java-archive");
        this.knownMimeTypes.put("java", "text/plain");
        this.knownMimeTypes.put("jnlp", "application/x-java-jnlp-file");
        this.knownMimeTypes.put("jpe", "image/jpeg");
        this.knownMimeTypes.put("jpeg", "image/jpeg");
        this.knownMimeTypes.put("jpg", "image/jpeg");
        this.knownMimeTypes.put("js", "text/javascript");
        this.knownMimeTypes.put("jsf", "text/plain");
        this.knownMimeTypes.put("jspf", "text/plain");
        this.knownMimeTypes.put("kar", "audio/x-midi");
        this.knownMimeTypes.put("latex", "application/x-latex");
        this.knownMimeTypes.put("log", "text/plain");
        this.knownMimeTypes.put("m3u", "audio/x-mpegurl");
        this.knownMimeTypes.put("mac", "image/x-macpaint");
        this.knownMimeTypes.put("man", "application/x-troff-man");
        this.knownMimeTypes.put("mathml", "application/mathml+xml");
        this.knownMimeTypes.put("me", "application/x-troff-me");
        this.knownMimeTypes.put("mid", "audio/x-midi");
        this.knownMimeTypes.put("midi", "audio/x-midi");
        this.knownMimeTypes.put("mif", "application/x-mif");
        this.knownMimeTypes.put("mov", "video/quicktime");
        this.knownMimeTypes.put("movie", "video/x-sgi-movie");
        this.knownMimeTypes.put("mp1", "audio/x-mpeg");
        this.knownMimeTypes.put("mp2", "audio/x-mpeg");
        this.knownMimeTypes.put("mp3", "audio/x-mpeg");
        this.knownMimeTypes.put("mp4", "video/mp4");
        this.knownMimeTypes.put("mpa", "audio/x-mpeg");
        this.knownMimeTypes.put("mpe", "video/mpeg");
        this.knownMimeTypes.put("mpeg", "video/mpeg");
        this.knownMimeTypes.put("mpega", "audio/x-mpeg");
        this.knownMimeTypes.put("mpg", "video/mpeg");
        this.knownMimeTypes.put("mpv2", "video/mpeg2");
        this.knownMimeTypes.put("ms", "application/x-wais-source");
        this.knownMimeTypes.put("nc", "application/x-netcdf");
        this.knownMimeTypes.put("ns2", "application/vnd.lotus-notes");
        this.knownMimeTypes.put("ns3", "application/vnd.lotus-notes");
        this.knownMimeTypes.put("ns4", "application/vnd.lotus-notes");
        this.knownMimeTypes.put("ns5", "application/vnd.lotus-notes");
        this.knownMimeTypes.put("ns6", "application/vnd.lotus-notes");
        this.knownMimeTypes.put("ns7", "application/vnd.lotus-notes");
        this.knownMimeTypes.put("ns8", "application/vnd.lotus-notes");
        this.knownMimeTypes.put("ns9", "application/vnd.lotus-notes");
        this.knownMimeTypes.put("nsf", "application/vnd.lotus-notes");
        this.knownMimeTypes.put("ntf", "application/vnd.lotus-notes");
        this.knownMimeTypes.put("oda", "application/oda");
        this.knownMimeTypes.put("odb", "application/vnd.oasis.opendocument.database");
        this.knownMimeTypes.put("odc", "application/vnd.oasis.opendocument.chart");
        this.knownMimeTypes.put("odf", "application/vnd.oasis.opendocument.formula");
        this.knownMimeTypes.put("odg", "application/vnd.oasis.opendocument.graphics");
        this.knownMimeTypes.put("odi", "application/vnd.oasis.opendocument.image");
        this.knownMimeTypes.put("odm", "application/vnd.oasis.opendocument.text-master");
        this.knownMimeTypes.put("odp", "application/vnd.oasis.opendocument.presentation");
        this.knownMimeTypes.put("ods", "application/vnd.oasis.opendocument.spreadsheet");
        this.knownMimeTypes.put("odt", "application/vnd.oasis.opendocument.text");
        this.knownMimeTypes.put("ogg", "application/ogg");
        this.knownMimeTypes.put("otg ", "application/vnd.oasis.opendocument.graphics-template");
        this.knownMimeTypes.put("oth", "application/vnd.oasis.opendocument.text-web");
        this.knownMimeTypes.put("otp", "application/vnd.oasis.opendocument.presentation-template");
        this.knownMimeTypes.put("ots", "application/vnd.oasis.opendocument.spreadsheet-template ");
        this.knownMimeTypes.put("ott", "application/vnd.oasis.opendocument.text-template");
        this.knownMimeTypes.put("pbm", "image/x-portable-bitmap");
        this.knownMimeTypes.put("pct", "image/pict");
        this.knownMimeTypes.put("pdf", "application/pdf");
        this.knownMimeTypes.put("pgm", "image/x-portable-graymap");
        this.knownMimeTypes.put("pic", "image/pict");
        this.knownMimeTypes.put("pict", "image/pict");
        this.knownMimeTypes.put("pls", "audio/x-scpls");
        this.knownMimeTypes.put("png", "image/png");
        this.knownMimeTypes.put("pnm", "image/x-portable-anymap");
        this.knownMimeTypes.put("pnt", "image/x-macpaint");
        this.knownMimeTypes.put("ppm", "image/x-portable-pixmap");
        this.knownMimeTypes.put("pps", "application/vnd.ms-powerpoint");
        this.knownMimeTypes.put("ppt", "application/vnd.ms-powerpoint");
        this.knownMimeTypes.put("pptx",
                "application/vnd.openxmlformats-officedocument.presentationml.presentation");
        this.knownMimeTypes.put("ps", "application/postscript");
        this.knownMimeTypes.put("psd", "image/x-photoshop");
        this.knownMimeTypes.put("qt", "video/quicktime");
        this.knownMimeTypes.put("qti", "image/x-quicktime");
        this.knownMimeTypes.put("qtif", "image/x-quicktime");
        this.knownMimeTypes.put("ras", "image/x-cmu-raster");
        this.knownMimeTypes.put("rdf", "application/rdf+xml");
        this.knownMimeTypes.put("rgb", "image/x-rgb");
        this.knownMimeTypes.put("rm", "application/vnd.rn-realmedia");
        this.knownMimeTypes.put("roff", "application/x-troff");
        this.knownMimeTypes.put("rtf", "application/rtf");
        this.knownMimeTypes.put("rtx", "text/richtext");
        this.knownMimeTypes.put("sh", "application/x-sh");
        this.knownMimeTypes.put("shar", "application/x-shar");
        this.knownMimeTypes.put("smf", "audio/x-midi");
        this.knownMimeTypes.put("sit", "application/x-stuffit");
        this.knownMimeTypes.put("snd", "audio/basic");
        this.knownMimeTypes.put("src", "application/x-wais-source");
        this.knownMimeTypes.put("sv4cpio", "application/x-sv4cpio");
        this.knownMimeTypes.put("sv4crc", "application/x-sv4crc");
        this.knownMimeTypes.put("svg", "image/svg+xml");
        this.knownMimeTypes.put("svgz", "image/svg+xml");
        this.knownMimeTypes.put("swf", "application/x-shockwave-flash");
        this.knownMimeTypes.put("t", "application/x-troff");
        this.knownMimeTypes.put("tar", "application/x-tar");
        this.knownMimeTypes.put("tcl", "application/x-tcl");
        this.knownMimeTypes.put("tex", "application/x-tex");
        this.knownMimeTypes.put("texi", "application/x-texinfo");
        this.knownMimeTypes.put("texinfo", "application/x-texinfo");
        this.knownMimeTypes.put("tif", "image/tiff");
        this.knownMimeTypes.put("tiff", "image/tiff");
        this.knownMimeTypes.put("tr", "application/x-troff");
        this.knownMimeTypes.put("tsv", "text/tab-separated-values");
        this.knownMimeTypes.put("txt", "text/plain");
        this.knownMimeTypes.put("ulw", "audio/basic");
        this.knownMimeTypes.put("ustar", "application/x-ustar");
        this.knownMimeTypes.put("vxml", "application/voicexml+xml");
        this.knownMimeTypes.put("xbm", "image/x-xbitmap");
        this.knownMimeTypes.put("xht", "application/xhtml+xml");
        this.knownMimeTypes.put("xhtml", "application/xhtml+xml");
        this.knownMimeTypes.put("xls", "application/vnd.ms-excel");
        this.knownMimeTypes.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        this.knownMimeTypes.put("xml", "application/xml");
        this.knownMimeTypes.put("xpm", "image/x-xpixmap");
        this.knownMimeTypes.put("xsl", "application/xml");
        this.knownMimeTypes.put("xslt", "application/xslt+xml");
        this.knownMimeTypes.put("xul", "application/vnd.mozilla.xul+xml");
        this.knownMimeTypes.put("xwd", "image/x-xwindowdump");
        this.knownMimeTypes.put("vsd", "application/x-visio");
        this.knownMimeTypes.put("wav", "audio/x-wav");
        this.knownMimeTypes.put("wbmp", "image/vnd.wap.wbmp");
        this.knownMimeTypes.put("webdav", "application/x-webdav");
        this.knownMimeTypes.put("wml", "text/vnd.wap.wml");
        this.knownMimeTypes.put("wmlc", "application/vnd.wap.wmlc");
        this.knownMimeTypes.put("wmls", "text/vnd.wap.wmlscript");
        this.knownMimeTypes.put("wmlscriptc", "application/vnd.wap.wmlscriptc");
        this.knownMimeTypes.put("wmv", "video/x-ms-wmv");
        this.knownMimeTypes.put("wrl", "x-world/x-vrml");
        this.knownMimeTypes.put("wspolicy", "application/wspolicy+xml");
        this.knownMimeTypes.put("Z", "application/x-compress");
        this.knownMimeTypes.put("z", "application/x-compress");
        this.knownMimeTypes.put("zip", "application/zip");
        // LOGGER.info("Loaded "+String.valueOf(this.knownMimeTypes.size())+" mime types");
    }

    // The next 4 methods ensure that it is a singleton

    /**
     * @param reset
     *            boolean -- if true the webDav manager gets setup freshly
     * @return the Singleton instance of the webDAV manager, should be loaded
     *         once only anyway
     */
    public static synchronized WebDavManager getManager(String servletPath, boolean reset) {

        if (reset || internalWebDavManager == null) {
            if (reset) {
                LOGGER.error("WebDAVManager reset executed");
            }
            initializeWebDavManager(servletPath);
        }
        return internalWebDavManager;
    }

    /**
     * @return the Singleton instance of the webDAV manager, should be loaded
     *         once only anyway
     */
    public static synchronized WebDavManager getManager(String servletPath) {
        return WebDavManager.getManager(servletPath, false);
    }

    /**
     * (non-Javadoc)
     * 
     * @see java.lang.Object#clone()
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // Singletons must NOT be cloned
        throw new CloneNotSupportedException();
    }

    /**
     * We make the constructor private, so you can't get to it
     */
    private WebDavManager() {

    }

    // Starting here are the class instance methods we actually use to return
    // values

    /**
     * List of maximum supported HTTP Methods loaded from methods.properties
     * This is the maxium of supported methods. Individual repositories might
     * implement only a subset of them
     */
    private Properties supportedMethods;

    /**
     * Lock Manager to allow locking of documents
     */
    private LockManager lockManager;

    /**
     * Meta Repository to hold the list of top level repositories
     */
    private DAVRepositoryMETA repositoryMeta;

    /**
     * @return Returns the lockManager.
     */
    public LockManager getLockManager() {
        if (this.lockManager != null) {
            return this.lockManager;
        }
        this.lockManager = LockManager.getLockManager();
        return this.lockManager;
    }

    /**
     * Loads all the supported HTTP keywords
     */
    private void loadSupportedMethods() {
        this.supportedMethods = new Properties();
        InputStream in = this.getClass().getResourceAsStream(WebDavManager.SUPPORTEDMETHODSFILE);
        try {
            this.supportedMethods.load(in);
            // FIXME - remove rawtimes
            for (@SuppressWarnings("rawtypes")
            Map.Entry curMethod : this.supportedMethods.entrySet()) {
                LOGGER.debug("Method: " + curMethod.getKey().toString() + " with class "
                        + curMethod.getValue().toString());
            }

        } catch (IOException e) {
            LOGGER.error(e);
        }

    }

    /**
     * loads the meta repository that contains all the repositories we currently
     * use as well as the global parameters now stored in the webDAVManager
     */
    private void loadMetaRepository() {
        // Load the Meta Repository -- and the style
        Properties metaProp = new Properties(); // to be loaded from file
        InputStream in = this.getClass().getResourceAsStream(WebDavManager.METAREPOPROPFILE);
        try {
            metaProp.load(in);
        } catch (IOException e) {
            LOGGER.error(e);
        }

        // Now load the values with sensible defaults
        String configLocation = metaProp.getProperty("repository-location",
                DAVRepositoryMETA.DEFAULT_REPOSITORY_LOCATION);
        String propfindStyle = metaProp.getProperty("style-name", DAVRepositoryMETA.DEFAULT_PROPFIND_STYLE);
        String rootStyle = metaProp.getProperty("root-style-name", DAVRepositoryMETA.DEFAULT_ROOT_STYLE);
        Boolean autoreload = new Boolean(metaProp.getProperty("auto-reload", "true"));
        Boolean canReset = new Boolean(metaProp.getProperty("allow-reset", "false"));
        String tempDir = metaProp.getProperty(INIT_KEY_TEMPDIR, DEFAULT_TMP_DIR);

        // Apply them to the repository and the manager
        this.repositoryMeta = DAVRepositoryMETA.getRepository(configLocation);
        this.repositoryMeta.setAutoReloadRepositoryList(autoreload.booleanValue());
        this.setRootPropfindStyle(rootStyle);
        this.setPropfindStyle(propfindStyle);
        this.setTempDir(tempDir);
        this.allowReset = canReset.booleanValue();

        // Write to the logger
        LOGGER.debug("Root-Style name:" + this.getRootPropfindStyle());
        LOGGER.debug("Repository-Style name:" + this.getPropfindStyle());
        LOGGER.debug("Configuration location:" + configLocation);
        LOGGER.debug("Can auto reload list:" + autoreload.toString());
        LOGGER.debug("Can reset:" + canReset.toString());
        LOGGER.debug("Temp Dir:" + tempDir);

    }

    /**
     * @param methodName
     *            the HTTP method we need
     * @return the classname for that method
     */
    public String getClassForMethod(String methodName) {

        if (this.supportedMethods == null) {
            this.loadSupportedMethods();
        }

        return this.supportedMethods.getProperty(methodName.toUpperCase());

    }

    /**
     * @return the repositoryMeta
     */
    public DAVRepositoryMETA getRepositoryMeta() {
        if (this.repositoryMeta == null) {
            this.loadMetaRepository();
        }
        return this.repositoryMeta;
    }

    /**
     * @param repositoryMeta
     *            the repositoryMeta to set
     */
    public void setRepositoryMeta(DAVRepositoryMETA repositoryMeta) {
        this.repositoryMeta = repositoryMeta;
    }

    /**
     * 
     * @return String XSLT Style for Propfind to make it look pretty in the
     *         browser
     */
    public String getPropfindStyle() {
        return this.propfindStyle;
    }

    /**
     * 
     * @param propfindStyle
     *            Style for Propfind
     */
    public void setPropfindStyle(String propfindStyle) {
        this.propfindStyle = propfindStyle;
    }

    /**
     * 
     * @return String XSLT Style for Propfind to make it look pretty in the
     *         browser
     */
    public String getRootPropfindStyle() {
        return this.rootPropfindStyle;
    }

    /**
     * 
     * @param propfindStyle
     *            Style for Propfind
     */
    public void setRootPropfindStyle(String propfindStyle) {
        this.rootPropfindStyle = propfindStyle;
    }

    /**
     * @param tempDir
     *            the directory for temporary file operations
     */
    public void setTempDir(String tempDir) {
        this.tempDir = tempDir;
    }

    /**
     * @return The current temporary directory
     */
    public String getTempDir() {
        if (this.tempDir == null) {
            this.tempDir = DEFAULT_TMP_DIR;
        }
        return this.tempDir;
    }

    /**
     * Retrieves mime types for known extensions
     * 
     * @param fileName
     * @return
     */
    public String getMimeType(String fileName) {

        String returnType = "application/octet-stream"; // Default value if
        // things go wrong
        int lastDot = fileName.lastIndexOf(".");
        if (lastDot < 0) {
            return returnType; // For files without extension we can't tell here
        }

        String extension = fileName.substring(lastDot + 1).toLowerCase();

        if (this.knownMimeTypes.containsKey(extension)) {
            returnType = this.knownMimeTypes.get(extension);
        }

        return returnType;
    }
}