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

Java tutorial

Introduction

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

Source

/** ========================================================================= *
 * Copyright (C) 2012 IBM Corporation                                         *
 *                            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.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import java.util.Stack;
import java.util.TimeZone;

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

import com.ibm.xsp.webdav.interfaces.IDAVXMLResponse;

/**
 * This class should not exist. It is manual XML, but Windows folder might need
 * it
 * 
 * @author Stephan H. Wissel
 * 
 */
public class DavXMLResponsePlain implements IDAVXMLResponse {

    /**
     * the prefix for every element (needs to be checked if that works)
     */
    private static final String DAV_PREFIX = "D:";

    /**
     * The namespace definition
     */
    private static final String DAV_NAMESPACE = "DAV:";

    /**
     * The namespace definition for auxiliary elements "DaveXTensions"
     */
    private static final String[] AUX_NAMESPACE = { "urn:schemas-microsoft-com:office:office",
            "http://schemas.microsoft.com/" };

    /**
     * the prefix for every element (needs to be checked if that works)
     */
    private static final String[] AUX_PREFIX = { "o:", "Repl" };

    /**
     * Logger for Errors
     */
    private static final Log LOGGER = LogFactory.getLog(DavXMLResponsePlain.class);

    // To avoid empty lines
    private boolean newLineSend = false;

    /**
     * The root element needs the namespace, so we track it here
     */
    private boolean rootElementWritten = false;

    /**
     * Will we write back more than DAV:
     */
    private boolean extendedResult = true;

    /**
     * What stylesheet to use as processing instruction
     */
    private String xmlStyleSheet = null;

    private ArrayList<String> tagsOnNewLine = null;

    /**
     * The writer we write out to
     */
    private StringBuilder out = null;

    /**
     * Keeping track of all open / closed XML tags
     */
    private Stack<String> xmlTagStack = new Stack<String>();

    /**
     * We can't write comments before we have the first element
     */
    private ArrayList<String> deferedComments;

    /**
     * creates as new XML reply that gets written out to the response writer
     * 
     * @param curResp
     */
    public DavXMLResponsePlain() {
    }

    /**
     * creates as new XML reply that gets written out to the response writer
     * adds an XML stylesheet processing instruction at the top to ensure nice
     * display in browsers
     * 
     * @param curResp
     * @param stylesheet
     */
    public DavXMLResponsePlain(String stylesheet, boolean extendedResult) {
        this.extendedResult = extendedResult;
        this.xmlStyleSheet = stylesheet;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.xsp.webdav.IDAVXMLResponse#addComment(java.lang.String)
     */
    public void addComment(String comment) {
        // Comment only gets written on extended results
        if (!this.extendedResult) {
            return;
        }
        if (!this.rootElementWritten) {
            if (this.deferedComments == null) {
                this.deferedComments = new ArrayList<String>();
            }
            this.deferedComments.add(comment);
        } else {
            out.append("\n<!-- ");
            out.append(comment);
            out.append(" -->");
        }

    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.xsp.webdav.IDAVXMLResponse#auxTag(java.lang.String,
     * java.lang.String)
     */
    public void auxTag(String tagName, String tagValue) {
        // Auxliliary Tag can be the first and only gets written on extended
        // results and always start on a new line
        if (!this.rootElementWritten || !this.extendedResult) {
            return;
        }

        if (!newLineSend) {
            out.append("\n");
        }
        out.append("<" + AUX_PREFIX[0] + tagName + ">");
        out.append(tagValue);
        out.append("</" + AUX_PREFIX[0] + tagName + ">\n");
        newLineSend = true;
    }

    public void auxPrefixedTag(String prefixName, String tagName, String tagValue) {
        // Auxliliary Tag can be the first and only gets written on extended
        // results and always start on a new line
        if (!this.rootElementWritten || !this.extendedResult) {
            return;
        }

        if (!newLineSend) {
            out.append("\n");
        }
        out.append("<" + prefixName + tagName + ">");
        out.append(tagValue);
        out.append("</" + prefixName + tagName + ">\n");
        newLineSend = true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.xsp.webdav.IDAVXMLResponse#cdataTag(java.lang.String,
     * java.lang.String)
     */
    public void cdataTag(String tagName, String tagValue) {
        this.openTag(tagName);
        out.append("<![CDATA[");
        out.append(tagValue);
        out.append("]]>");
        this.closeTag(1);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.xsp.webdav.IDAVXMLResponse#closeDocument()
     */
    public void closeDocument() {
        this.closeTag(-1); // Make sure all tages are closes
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.xsp.webdav.IDAVXMLResponse#closeTag(int)
     */
    public void closeTag(int howMany) {

        if (howMany < 0) {
            while (!this.xmlTagStack.empty()) {
                String closeTag = this.xmlTagStack.pop();
                out.append("</" + DAV_PREFIX + closeTag + ">");
                doNewLineIfNeeded(closeTag);
            }
        } else {
            for (int i = 0; i < howMany; i++) {
                if (!this.xmlTagStack.empty()) {
                    String closeTag = this.xmlTagStack.pop();
                    out.append("</" + DAV_PREFIX + closeTag + ">");
                    doNewLineIfNeeded(closeTag);
                } else {
                    break; // No point looping
                }
            }
        }
    }

    private void doNewLineIfNeeded(String closeTag) {
        if (getNewLineForTag(closeTag)) {
            out.append("\n");
            newLineSend = true;
        } else {
            newLineSend = false;
        }

    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.xsp.webdav.IDAVXMLResponse#closeTag(java.lang.String)
     */
    public boolean closeTag(String lastTagToClose) {

        boolean result = false;

        while (!this.xmlTagStack.empty()) {

            String closeTag = this.xmlTagStack.pop();
            out.append("</" + DAV_PREFIX + closeTag + ">");
            doNewLineIfNeeded(closeTag);
            if (closeTag.equals(lastTagToClose)) {
                result = true;
                break;
            }
        }

        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.xsp.webdav.IDAVXMLResponse#emptyTag(java.lang.String)
     */
    public void emptyTag(String tagName) {

        if ("source".equals(tagName)) {
            this.openTag(tagName);
            this.closeTag(1);
        } else {
            boolean doNewLine = getNewLineForTag(tagName);
            if (doNewLine && !newLineSend) {
                out.append("\n");
            }
            out.append("<" + DAV_PREFIX + tagName + "/>");
            if (doNewLine) {
                out.append("\n");
            }
            newLineSend = doNewLine;
        }

    }

    /**
     * Returns the XML for the current document. Nice to be written into the
     * response
     * 
     * @return
     */
    // public byte[] getXMLBytes() {
    // return this.out.toByteArray();
    // }
    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.xsp.webdav.IDAVXMLResponse#openTag(java.lang.String)
     */
    public void openTag(String tagName) {

        if (this.rootElementWritten) {
            if (getNewLineForTag(tagName) && !newLineSend) {
                out.append("\n");
            }
            newLineSend = false;
            out.append("<" + DAV_PREFIX + tagName + ">");
            this.xmlTagStack.push(tagName);
        } else {
            this.startNewResponseBody(tagName);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.xsp.webdav.IDAVXMLResponse#simpleTag(java.lang.String,
     * java.lang.String)
     */
    public void simpleTag(String tagName, String tagValue) {
        this.openTag(tagName);
        out.append(tagValue);
        this.closeTag(1);
    }

    /**
     * Starts a new XML document and inserts the correct starting tag with name
     * spaces
     * 
     * @param tagName
     */
    private void startNewResponseBody(String tagName) {

        LOGGER.debug("New simple XML started");
        this.out = new StringBuilder();
        out.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");

        if (this.xmlStyleSheet != null && this.extendedResult) {
            // Stylesheet if we have one and we are on extended results
            out.append("<?xml-stylesheet type=\"text/xsl\" href=\"" + this.xmlStyleSheet + "\"?>\n");
        }

        String nsShort = DAV_PREFIX.substring(0, (DAV_PREFIX.length() - 1));
        out.append("<" + DAV_PREFIX + tagName + " xmlns:" + nsShort + "=\"" + DAV_NAMESPACE + "\"");
        if (this.extendedResult) {
            for (int i = 0; i < AUX_PREFIX.length; i++) {
                String auxShort = AUX_PREFIX[i].substring(0, (AUX_PREFIX[i].length() - 1));
                out.append(" xmlns:" + auxShort + "=\"" + AUX_NAMESPACE[i] + "\"");
            }
        }
        out.append(">");

        this.xmlTagStack.push(tagName);
        this.rootElementWritten = true; // We memorize that

        // If there are defered commends process them
        if (this.deferedComments != null) {
            for (String curComment : this.deferedComments) {
                this.addComment(curComment);
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.ibm.xsp.webdav.IDAVXMLResponse#dateTagForCreateDate(java.lang.String,
     * java.util.Date)
     */
    public void dateTagForCreateDate(String TagName, Date date) {
        if (date == null) {
            return;
        }

        // "2005-08-10T10:19:24Z";
        /*
         * String[] dateParsed=date.toString().split(" "); String
         * timeZone=dateParsed[dateParsed.length-2];
         * if(timeZone.equals("EET")||timeZone.equals("EEST")){ timeZone="GMT";
         * }
         */
        String creatFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'";
        SimpleDateFormat fmt = new SimpleDateFormat(creatFormat, Locale.UK);
        String datestring = fmt.format(date);
        this.simpleTag(TagName, datestring);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.xsp.webdav.IDAVXMLResponse#dateTag(java.lang.String,
     * java.util.Date)
     */
    public void dateTag(String TagName, Date date) {
        if (date == null) {
            return;
        }
        // "Sat, 26 Mar 2005 11:22:20 GMT";
        String[] dateParsed = date.toString().split(" ");
        String timeZone = dateParsed[dateParsed.length - 2];
        if (timeZone.equals("EEST")) {
            timeZone = "EET";
        }
        if (timeZone.equals("EET") || timeZone.equals("ZE2")) {

            // if(TimeZone.getTimeZone(timeZone).getRawOffset()>0){
            // LOGGER.info("Time zone="+timeZone);
            // LOGGER.info("Time offset="+ new Integer
            // (TimeZone.getTimeZone(timeZone).getRawOffset()).toString());
            date = new Date(date.getTime() - TimeZone.getTimeZone(timeZone).getRawOffset());
            timeZone = "GMT";
        }
        String lastmodFormat = "EE', 'd' 'MMM' 'yyyy' 'HH':'mm':'ss";
        //Locale.UK is the secret to make it work in Win7!
        SimpleDateFormat fmt = new SimpleDateFormat(lastmodFormat, Locale.UK);
        String datestring = fmt.format(date);
        this.simpleTag(TagName, datestring + " " + timeZone);

    }

    @Override
    public String toString() {
        if (this.out != null) {
            return this.out.toString();
        }
        return super.toString();
    }

    /**
     * Not all Tags start on a new line
     * 
     * @param tagName
     * @return
     */
    private boolean getNewLineForTag(String tagName) {
        if (this.tagsOnNewLine == null) {
            this.loadTagsOnNewLine();
        }
        return this.tagsOnNewLine.contains(tagName);
    }

    private void loadTagsOnNewLine() {
        tagsOnNewLine = new ArrayList<String>();
        tagsOnNewLine.add("multistatus");
        tagsOnNewLine.add("response");
        tagsOnNewLine.add("propstat");
        tagsOnNewLine.add("displayname");
        tagsOnNewLine.add("resoucetype");
        tagsOnNewLine.add("source");
        tagsOnNewLine.add("supportedlock");
        tagsOnNewLine.add("lockdiscovery");
        tagsOnNewLine.add("status");
        tagsOnNewLine.add("getlastmodified");
        tagsOnNewLine.add("getcontentlength");
        tagsOnNewLine.add("getetag");
        tagsOnNewLine.add("getcontenttype");
    }
}