Java tutorial
/** ========================================================================= * * 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.ByteArrayOutputStream; import java.io.IOException; import java.io.StringWriter; 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 javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import com.ibm.xsp.webdav.interfaces.IDAVXMLResponse; /** * The DavXMLResponse renders XML that is returned from PROPFIND or LOCK into * the respective XML structure into the DAV: namespace. Not really relevant for * web access but critical when accessing the stuff through a webDAV client like * webfolders in Windows Explorer * * @author Stephan H. Wissel * */ public class DavXMLResponse implements IDAVXMLResponse { /** * the prefix for every element (needs to be checked if that works) */ private static final String DAV_PREFIX = "D:"; private Locale DAV_LOCALE = Locale.getDefault(); /** * The namespace definition */ private static final String DAV_NAMESPACE = "DAV:"; /** * The namespace definition for auxiliary elements "DaveXTensions" */ private static final String AUX_NAMESPACE = "DXT:"; /** * the prefix for every element (needs to be checked if that works) */ private static final String AUX_PREFIX = "dxt:"; /** * Logger for Errors */ private static final Log LOGGER = LogFactory.getLog(DavXMLResponse.class); /** * 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 = false; /** * What stylesheet to use as processing instruction */ private String xmlStyleSheet = null; /** * The writer we write out to */ // private ByteArrayOutputStream out = null; private StringWriter out = null; /** * The stream result for the XML document */ private StreamResult streamResult = 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; /** * Where we write out all the XML content */ TransformerHandler body = null; /** * creates as new XML reply that gets written out to the response writer * * @param curResp */ public DavXMLResponse() { } /** * 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 DavXMLResponse(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 { try { body.comment(comment.toCharArray(), 0, comment.length()); } catch (SAXException e) { LOGGER.error(e); } } } /* * (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 if (!this.rootElementWritten || !this.extendedResult) { return; } try { body.startElement("", tagName, AUX_PREFIX + tagName, null); body.characters(tagValue.toCharArray(), 0, tagValue.length()); body.endElement("", tagName, AUX_PREFIX + tagName); } catch (SAXException e) { LOGGER.error(e); } } /* * (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); try { body.startCDATA(); body.characters(tagValue.toCharArray(), 0, tagValue.length()); body.endCDATA(); } catch (SAXException e) { LOGGER.error(e); } this.closeTag(1); } /* * (non-Javadoc) * * @see com.ibm.xsp.webdav.IDAVXMLResponse#closeDocument() */ public void closeDocument() { this.closeTag(-1); // Make sure all tages are closes try { this.body.endDocument(); this.out.flush(); this.out.close(); } catch (SAXException e) { LOGGER.error(e); } catch (IOException e) { LOGGER.error(e); } } /* * (non-Javadoc) * * @see com.ibm.xsp.webdav.IDAVXMLResponse#closeTag(int) */ public void closeTag(int howMany) { if (howMany < 0) { while (!this.xmlTagStack.empty()) { try { String closeTag = this.xmlTagStack.pop(); body.endElement("", closeTag, DAV_PREFIX + closeTag); } catch (SAXException e) { LOGGER.error(e); break; } } } else { for (int i = 0; i < howMany; i++) { if (!this.xmlTagStack.empty()) { try { String closeTag = this.xmlTagStack.pop(); body.endElement("", closeTag, DAV_PREFIX + closeTag); } catch (SAXException e) { LOGGER.error(e); break; } } else { break; // No point looping } } } } /* * (non-Javadoc) * * @see com.ibm.xsp.webdav.IDAVXMLResponse#closeTag(java.lang.String) */ public boolean closeTag(String lastTagToClose) { boolean result = false; while (!this.xmlTagStack.empty()) { try { String closeTag = this.xmlTagStack.pop(); body.endElement("", closeTag, DAV_PREFIX + closeTag); if (closeTag.equals(lastTagToClose)) { result = true; break; } } catch (SAXException e) { LOGGER.error(e); break; } } return result; } /* * (non-Javadoc) * * @see com.ibm.xsp.webdav.IDAVXMLResponse#emptyTag(java.lang.String) */ public void emptyTag(String tagName) { this.openTag(tagName); this.closeTag(1); } /** * Gets the transformer handler object where we write everything to * * @param streamResult * the place where we write the result to * @return the body object to append XML tags to */ private TransformerHandler getSAXOutputObject(StreamResult streamResult) { // Factory pattern at work SAXTransformerFactory tf = (SAXTransformerFactory) TransformerFactory.newInstance(); // SAX2.0 ContentHandler that provides the append point and access to // serializing options TransformerHandler hd; try { hd = tf.newTransformerHandler(); Transformer serializer = hd.getTransformer(); serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");// Suitable // for // all // languages serializer.setOutputProperty(OutputKeys.METHOD, "xml"); if (this.extendedResult || true) { serializer.setOutputProperty(OutputKeys.INDENT, "yes"); } hd.setResult(streamResult); return hd; } catch (TransformerConfigurationException e) { LOGGER.error(e); } return null; } /** * 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) { try { body.startElement("", tagName, DAV_PREFIX + tagName, null); this.xmlTagStack.push(tagName); } catch (SAXException e) { LOGGER.error(e); } } 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); try { body.characters(tagValue.toCharArray(), 0, tagValue.length()); } catch (SAXException e) { LOGGER.error(e); } catch (NullPointerException e) { LOGGER.error(e); } this.closeTag(1); } /** * Starts a new XML document and inserts the correct starting tag with name * spaces * * @param tagName */ private void startNewResponseBody(String tagName) { // this.out = new ByteArrayOutputStream(); this.out = new StringWriter(); if (this.out != null) { this.streamResult = new StreamResult(out); this.body = this.getSAXOutputObject(streamResult); try { // Start the document this.body.startDocument(); // Stylesheet if we have one and we are on extended results if (this.xmlStyleSheet != null && this.extendedResult) { this.body.processingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"" + this.xmlStyleSheet + "\""); } // First tag with correct namespaces AttributesImpl attr = new AttributesImpl(); String nsShort = DAV_PREFIX.substring(0, (DAV_PREFIX.length() - 1)); String auxShort = AUX_PREFIX.substring(0, (AUX_PREFIX.length() - 1)); attr.addAttribute("", nsShort, "xmlns:" + nsShort, "String", DAV_NAMESPACE); if (this.extendedResult) { attr.addAttribute("", auxShort, "xmlns:" + auxShort, "String", AUX_NAMESPACE); } this.body.startElement("", tagName, DAV_PREFIX + tagName, attr); 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); } } } catch (SAXException e) { LOGGER.error(e); } } else { LOGGER.error("Can't start an XML body for the response"); } } /* * (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; date = new Date(); } // "2005-08-10T10:19:24Z"; String creatFormat = "yyyy'-'MM'-'d'T0'H':'m':'s'Z'"; SimpleDateFormat fmt = new SimpleDateFormat(creatFormat, DAV_LOCALE); fmt.setTimeZone(TimeZone.getTimeZone("GMT")); 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) { date = new Date(); // return; } // "Sat, 26 Mar 2005 11:22:20 GMT"; String lastmodFormat = "EE', 'd' 'MMM' 'yyyy' 'H':'m':'s' 'z"; SimpleDateFormat fmt = new SimpleDateFormat(lastmodFormat, DAV_LOCALE); fmt.setTimeZone(TimeZone.getTimeZone("GMT")); String datestring = fmt.format(date); this.simpleTag(TagName, datestring); } @Override public String toString() { if (this.out != null) { return this.out.toString(); } return super.toString(); } public void setLocale(Locale l) { this.DAV_LOCALE = l; } }