package com.ejie.x38.webdav.methods; import java.io.IOException; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Vector; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.InputSource; import com.ejie.x38.webdav.ITransaction; import com.ejie.x38.webdav.IWebdavStore; import com.ejie.x38.webdav.StoredObject; import com.ejie.x38.webdav.WebdavStatus; import com.ejie.x38.webdav.exceptions.AccessDeniedException; import com.ejie.x38.webdav.exceptions.LockFailedException; import com.ejie.x38.webdav.exceptions.WebdavException; import com.ejie.x38.webdav.fromcatalina.XMLHelper; import com.ejie.x38.webdav.fromcatalina.XMLWriter; import com.ejie.x38.webdav.locking.LockedObject; import com.ejie.x38.webdav.locking.IResourceLocks; public class DoProppatch extends AbstractMethod { private static org.slf4j.Logger LOG = org.slf4j.LoggerFactory .getLogger(DoProppatch.class); private boolean _readOnly; private IWebdavStore _store; private IResourceLocks _resourceLocks; public DoProppatch(IWebdavStore store, IResourceLocks resLocks, boolean readOnly) { _readOnly = readOnly; _store = store; _resourceLocks = resLocks; } public void execute(ITransaction transaction, HttpServletRequest req, HttpServletResponse resp) throws IOException, LockFailedException { LOG.trace("-- " + this.getClass().getName()); if (_readOnly) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return; } String path = getRelativePath(req); String parentPath = getParentPath(getCleanPath(path)); Hashtable<String, Integer> errorList = new Hashtable<String, Integer>(); if (!checkLocks(transaction, req, resp, _resourceLocks, parentPath)) { errorList.put(parentPath, WebdavStatus.SC_LOCKED); sendReport(req, resp, errorList); return; // parent is locked } if (!checkLocks(transaction, req, resp, _resourceLocks, path)) { errorList.put(path, WebdavStatus.SC_LOCKED); sendReport(req, resp, errorList); return; // resource is locked } // TODO for now, PROPPATCH just sends a valid response, stating that // everything is fine, but doesn't do anything. // Retrieve the resources String tempLockOwner = "doProppatch" + System.currentTimeMillis() + req.toString(); if (_resourceLocks.lock(transaction, path, tempLockOwner, false, 0, TEMP_TIMEOUT, TEMPORARY)) { StoredObject so = null; LockedObject lo = null; try { so = _store.getStoredObject(transaction, path); lo = _resourceLocks.getLockedObjectByPath(transaction, getCleanPath(path)); if (so == null) { resp.sendError(HttpServletResponse.SC_NOT_FOUND); return; // we do not to continue since there is no root // resource } if (so.isNullResource()) { String methodsAllowed = DeterminableMethod .determineMethodsAllowed(so); resp.addHeader("Allow", methodsAllowed); resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED); return; } if (lo != null && lo.isExclusive()) { // Object on specified path is LOCKED errorList = new Hashtable<String, Integer>(); errorList.put(path, new Integer(WebdavStatus.SC_LOCKED)); sendReport(req, resp, errorList); return; } List<String> toset = null; List<String> toremove = null; List<String> tochange = new Vector<String>(); // contains all properties from // toset and toremove path = getCleanPath(getRelativePath(req)); Node tosetNode = null; Node toremoveNode = null; if (req.getContentLength() != 0) { DocumentBuilder documentBuilder = getDocumentBuilder(); try { Document document = documentBuilder .parse(new InputSource(req.getInputStream())); // Get the root element of the document Element rootElement = document.getDocumentElement(); tosetNode = XMLHelper.findSubElement(XMLHelper .findSubElement(rootElement, "set"), "prop"); toremoveNode = XMLHelper.findSubElement(XMLHelper .findSubElement(rootElement, "remove"), "prop"); } catch (Exception e) { resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR); return; } } else { // no content: error resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR); return; } HashMap<String, String> namespaces = new HashMap<String, String>(); namespaces.put("DAV:", "D"); if (tosetNode != null) { toset = XMLHelper.getPropertiesFromXML(tosetNode); tochange.addAll(toset); } if (toremoveNode != null) { toremove = XMLHelper.getPropertiesFromXML(toremoveNode); tochange.addAll(toremove); } resp.setStatus(WebdavStatus.SC_MULTI_STATUS); resp.setContentType("text/xml; charset=UTF-8"); // Create multistatus object XMLWriter generatedXML = new XMLWriter(resp.getWriter(), namespaces); generatedXML.writeXMLHeader(); generatedXML .writeElement("DAV::multistatus", XMLWriter.OPENING); generatedXML.writeElement("DAV::response", XMLWriter.OPENING); String status = new String("HTTP/1.1 " + WebdavStatus.SC_OK + " " + WebdavStatus.getStatusText(WebdavStatus.SC_OK)); // Generating href element generatedXML.writeElement("DAV::href", XMLWriter.OPENING); String href = req.getContextPath(); if ((href.endsWith("/")) && (path.startsWith("/"))) href += path.substring(1); else href += path; if ((so.isFolder()) && (!href.endsWith("/"))) href += "/"; generatedXML.writeText(rewriteUrl(href)); generatedXML.writeElement("DAV::href", XMLWriter.CLOSING); for (Iterator<String> iter = tochange.iterator(); iter .hasNext();) { String property = (String) iter.next(); generatedXML.writeElement("DAV::propstat", XMLWriter.OPENING); generatedXML.writeElement("DAV::prop", XMLWriter.OPENING); generatedXML.writeElement(property, XMLWriter.NO_CONTENT); generatedXML.writeElement("DAV::prop", XMLWriter.CLOSING); generatedXML.writeElement("DAV::status", XMLWriter.OPENING); generatedXML.writeText(status); generatedXML.writeElement("DAV::status", XMLWriter.CLOSING); generatedXML.writeElement("DAV::propstat", XMLWriter.CLOSING); } generatedXML.writeElement("DAV::response", XMLWriter.CLOSING); generatedXML .writeElement("DAV::multistatus", XMLWriter.CLOSING); generatedXML.sendData(); } catch (AccessDeniedException e) { resp.sendError(WebdavStatus.SC_FORBIDDEN); } catch (WebdavException e) { resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR); } catch (ServletException e) { e.printStackTrace(); // To change body of catch statement use // File | Settings | File Templates. } finally { _resourceLocks.unlockTemporaryLockedObjects(transaction, path, tempLockOwner); } } else { resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR); } } }