mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
29870: ALF-9952: Compatibility fix to allow mounting of Alfresco WebDAV as a network drive on Windows XP (without WebDrive) 29872: Fixed ALF-7698 "Defects in tags picker in SHARE." - now checks added items to avoid duplicates 29873: Made sure the onActionDetails doclib action generates SimpleDialog instance ids each time, to avoid multiple js class instances with the same id getting called for every dialog created. 29878: ALF-9378: Use caching plus a read write lock, in a similar manner to ALF-7064, to avoid contention in SubsystemProxyFactory under load 29881: Added helper text for the translators to the property file. 29910: ALF-7433: a file deleted using the web UI still appears in a NFS mount but with NULL stats - timestamp propagation now enabled by default so NFS always works - timestamp propagation less agressive - only has to propagate on adds / deletes and renames 29911: Values for recurrence strings updated now that I've read RFC-2445 29944: ALF-9988: Merged PATCHES/V3.3.4 to V3.4-BUG-FIX 28581: ALF-8944: Corrected sort parameter handling for datetime fields, based on analyzer and tokenization mode 29955: Fixed ALF-9965: Property names matching fails if the property contains non Alphanumeric characters 29956: Fixed ALF-9424: Webform(XSD): xf:switch switch group does not work based on "complexContent with Base" element. 29964: Fixed ALF-9089: TinyMCE convert_fonts_to_spans parameter is not being picked up in Web Forms 29977: L10N Updates from Gloria (based on rev29838). 29980: Ignore virtual tomcat directory 29981: Merged BRANCHES/DEV/BELARUS/V3.4-BUG-FIX-2011_08_19 to BRANCHES/DEV/V3.4-BUG-FIX ALF-6808 : Incorrect Search Language Conversion for wild card characters (%, _) for MS SQL 29984: ALF-4753: Fix search query escaping in Alfresco Explorer - AWC-1743 / CHK-2171 fix restored 29993: Merged DEV/TEMPORARY to V3.4-BUG-FIX 29989: ALF-9976: WebDAV Class 2 compliance issue with OPTIONS response. Class 2 incompliance connected with absence of 'PROPPATCH' method in the 'Allow' response header has been fixed 30009: ALF-7239 : Documents from Records Manager cannot be viewed in Outlook 30012: Merged BRANCHES/DEV/BELARUS/V3.4-BUG-FIX-2011_08_19 to BRANCHES/DEV/V3.4-BUG-FIX: 29986: ALF-7105: pdfbox returns errors in the logs but one cannot understand what file is affected (PDFBox) 30014: ALF-6284: Fix for Share Kerberos SSO Websphere compatibility (by Pavel) 30016: Merged DEV to V3.4-BUG-FIX 29424: ALF-8715: NFS: Admin sometimes cannot edit content uploaded via JSF Fix for "Can't open file for writing" during saving file in VI-like editors connected with FileExpiry daemon: - 'getNodeOrNull()' method extracted to get and check on existence of the cached file object and then update cache timeout or remove it from the cache; - 'getNodeForPath()' was appropriately updated in accordance with logic extracted to 'getNodeOrNull()'; - 'fileExists()' method was corrected to take into account existence of the cached file object 30017: Reverses an accidental check in made with the last L10N bundle update (r29977) 30045: ALF-8664 - Custom 'mandatory' RM metadata causes editing issues 30053: ALF-9681: webScriptsRegistryCache size in ehcache-default.xml webScriptsRegistryCache maxElementsInMemory size was incremented up to 1000 30079: ALF-10027: Fix template alfresco-global.properties for custom tomcat ports - Obselete web.application.context.url removed - alfresco.host, alfresco.port, share.host and share.port added 30080: Fixed parse error mentioned in ALF-9511 "RSS Feeds with HTTP Auth doesn't work with Feed dashlet" - In java regexps the . (dot) does NOT include the \r or \n by default, to change that a (?s) instruction was added in the beginning of the regexp 30083: Fixed ALF-10048 "Multiple thumbnails in RSS feeds causes problem for RSS Feed dashlet" 30088: ALF-7433: Fix unit test fallout from new timestamp propagation behaviour 30089: ALF-7433: Further unit test fallout from new timestamp propagation behaviour - testPermissionsAndPolicies needs to get folder modification date in a distinct transaction after populating it 30091: ALF-10050: CIFS: Coordinator is unable to delete content after IMAP has been enabled - Transactional cache null entry issue 30096: ALF-9793: Allow auto-created NFS authenticated users to work - Also removed admin from default mappings to avoid security hole 30102: ALF-8723 CIFS on Windows fails to start under certain conditions - Found another place >= was required rather than just > 30104: ALF-9890 SiteService is not producing audit data. - Internal siteService rather than public SiteService was being used, so there was no audit advice. 30119: ALF-9793: Fallout from previous fix. Prevent initialization error when there are no user mappings and NFS is not enabled. 30120: ALF-9526: Work around the fact that Websphere ignores the response encoding unless you call response.setCharacterEncoding() - GlobalLocalizationFilter inserts a response wrapper that parses the charset parameter from the content type header, if it is present 30121: ALF-9535: Alfresco ignores Accept-Language sent from Share - Ticket and webscript authentication (i.e. Share requests) will use the language set in request headers as the session language 30130: ALF-10049: Fix by Andrey to enable Flash upload on Weblogic! 30141: ALF-8732 Now if the adhoc workflow throws exceptions while sending a notification email then those exceptions are ignored. 30226: ALF-9415: JSF - Copy/Paste vs Cut/Paste add aspect rule. 30242: Added NodeService.getNodeRef(Long nodeId) - First step to remove Lucene search from inbound email server - Done while investigating ALF-9660 30243: Fixed ALF-9660: Inbound emails are always stored with encoding=UTF-8 regardless the encoding the email client uses. - If the encoding is provided, then it is not guessed - Includes tweak to remove Lucene search and rather use direct node ID-NodeRef translation provided by NodeService 30263: Incremented version revision 30264: ALF-10187: Merged V3.3 to V3.4-BUG-FIX 30003: ALF-9898: More defensive exception handling to avoid packet pool leaks and extra logging on packet pool exhaustion 30265: Merged V3.4 to V3.4-BUG-FIX 30259: ALF-6527 LangPack FR - [Search results' page] Incorrect label when search matches results - Added "(s)" to "trouvé(s) dans l'entrepôt." (for a repository search - found in retest) - The original change: Added "(s)" to "trouvé(s) dans tous les sites." (for an All Sites search) However this leaves the current site search. As a result I also: Added "(s)" to "trouvé(s) dans le site {0}." (for a current Site search) and checked with a French speaker that this would sound correct. Note: all three labels are prefixed by a separate text label: "N résultat(s) " 30261: (RECORD ONLY) Merged V3.4-BUG-FIX to V3.4 (3.4.5) 30262: ALF-10186: Merged PATCHES/V3.4.1 to V3.4 30126: ALF-10075: Concurrency during CMIS document update causes content stream to close prematurely. - Created BufferedRequest request wrapper in RepositoryContainer - If the content stream is accessed directly it is streamed to a temporary file so that requests can be retried 30137: ALF-10075: Fixed NPE git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@30271 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
982 lines
38 KiB
Java
982 lines
38 KiB
Java
/*
|
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
|
*
|
|
* This file is part of Alfresco
|
|
*
|
|
* Alfresco is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Alfresco 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package org.alfresco.repo.webdav;
|
|
|
|
import java.io.IOException;
|
|
import java.io.Serializable;
|
|
import java.util.ArrayList;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
import org.alfresco.error.AlfrescoRuntimeException;
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.repo.SessionUser;
|
|
import org.alfresco.repo.webdav.auth.AuthenticationFilter;
|
|
import org.alfresco.service.cmr.model.FileFolderService;
|
|
import org.alfresco.service.cmr.model.FileInfo;
|
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
|
import org.alfresco.service.cmr.repository.ContentData;
|
|
import org.alfresco.service.cmr.repository.Path;
|
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
|
import org.alfresco.service.cmr.repository.datatype.TypeConverter;
|
|
import org.alfresco.service.namespace.QName;
|
|
import org.dom4j.DocumentHelper;
|
|
import org.dom4j.io.OutputFormat;
|
|
import org.dom4j.io.XMLWriter;
|
|
import org.w3c.dom.Document;
|
|
import org.w3c.dom.Element;
|
|
import org.w3c.dom.Node;
|
|
import org.w3c.dom.NodeList;
|
|
import org.xml.sax.Attributes;
|
|
import org.xml.sax.SAXException;
|
|
import org.xml.sax.helpers.AttributesImpl;
|
|
|
|
/**
|
|
* Implements the WebDAV PROPFIND method
|
|
*
|
|
* @author Gavin Cornwell
|
|
*/
|
|
public class PropFindMethod extends WebDAVMethod
|
|
{
|
|
// Request types
|
|
protected static final int GET_ALL_PROPS = 0;
|
|
protected static final int GET_NAMED_PROPS = 1;
|
|
protected static final int FIND_PROPS = 2;
|
|
|
|
// Find request type
|
|
protected int m_mode = GET_ALL_PROPS;
|
|
|
|
// Requested properties
|
|
protected ArrayList<WebDAVProperty> m_properties = null;
|
|
|
|
// Available namespaces list
|
|
protected HashMap<String, String> m_namespaces = null;
|
|
|
|
/**
|
|
* Default constructor
|
|
*/
|
|
public PropFindMethod()
|
|
{
|
|
m_namespaces = new HashMap<String, String>();
|
|
}
|
|
|
|
/**
|
|
* Return the find mode
|
|
*
|
|
* @return int
|
|
*/
|
|
public final int getMode()
|
|
{
|
|
return m_mode;
|
|
}
|
|
|
|
/**
|
|
* Parse the request headers
|
|
*
|
|
* @exception WebDAVServerException
|
|
*/
|
|
protected void parseRequestHeaders() throws WebDAVServerException
|
|
{
|
|
// Store the Depth header as this is used by several WebDAV methods
|
|
|
|
parseDepthHeader();
|
|
|
|
}
|
|
|
|
/**
|
|
* Parse the request body
|
|
*
|
|
* @exception WebDAVServerException
|
|
*/
|
|
protected void parseRequestBody() throws WebDAVServerException
|
|
{
|
|
Document body = getRequestBodyAsDocument();
|
|
if (body != null)
|
|
{
|
|
Element rootElement = body.getDocumentElement();
|
|
NodeList childList = rootElement.getChildNodes();
|
|
Node node = null;
|
|
|
|
for (int i = 0; i < childList.getLength(); i++)
|
|
{
|
|
Node currentNode = childList.item(i);
|
|
switch (currentNode.getNodeType())
|
|
{
|
|
case Node.TEXT_NODE:
|
|
break;
|
|
case Node.ELEMENT_NODE:
|
|
if (currentNode.getNodeName().endsWith(WebDAV.XML_ALLPROP))
|
|
{
|
|
m_mode = GET_ALL_PROPS;
|
|
}
|
|
else if (currentNode.getNodeName().endsWith(WebDAV.XML_PROP))
|
|
{
|
|
m_mode = GET_NAMED_PROPS;
|
|
node = currentNode;
|
|
}
|
|
else if (currentNode.getNodeName().endsWith(WebDAV.XML_PROPNAME))
|
|
{
|
|
m_mode = FIND_PROPS;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (m_mode == GET_NAMED_PROPS)
|
|
{
|
|
m_properties = new ArrayList<WebDAVProperty>();
|
|
childList = node.getChildNodes();
|
|
|
|
for (int i = 0; i < childList.getLength(); i++)
|
|
{
|
|
Node currentNode = childList.item(i);
|
|
switch (currentNode.getNodeType())
|
|
{
|
|
case Node.TEXT_NODE:
|
|
break;
|
|
case Node.ELEMENT_NODE:
|
|
m_properties.add(createProperty(currentNode));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return Returns <tt>true</tt> always
|
|
*/
|
|
@Override
|
|
protected boolean isReadOnly()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Execute the main WebDAV request processing
|
|
*
|
|
* @exception WebDAVServerException
|
|
*/
|
|
protected void executeImpl() throws WebDAVServerException, Exception
|
|
{
|
|
m_response.setStatus(WebDAV.WEBDAV_SC_MULTI_STATUS);
|
|
|
|
FileFolderService fileFolderService = getFileFolderService();
|
|
|
|
FileInfo pathNodeInfo = null;
|
|
try
|
|
{
|
|
// Check that the path exists
|
|
pathNodeInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), m_strPath, m_request.getServletPath());
|
|
}
|
|
catch (FileNotFoundException e)
|
|
{
|
|
// The path is not valid - send a 404 error back to the client
|
|
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
|
|
}
|
|
|
|
// Set the response content type
|
|
|
|
m_response.setContentType(WebDAV.XML_CONTENT_TYPE);
|
|
|
|
// Create multistatus response
|
|
|
|
XMLWriter xml = createXMLWriter();
|
|
|
|
xml.startDocument();
|
|
|
|
String nsdec = generateNamespaceDeclarations(m_namespaces);
|
|
xml.startElement(
|
|
WebDAV.DAV_NS,
|
|
WebDAV.XML_MULTI_STATUS + nsdec,
|
|
WebDAV.XML_NS_MULTI_STATUS + nsdec,
|
|
getDAVHelper().getNullAttributes());
|
|
|
|
// Create the path for the current location in the tree
|
|
StringBuilder baseBuild = new StringBuilder(256);
|
|
baseBuild.append(getPath());
|
|
if (baseBuild.length() == 0 || baseBuild.charAt(baseBuild.length() - 1) != WebDAVHelper.PathSeperatorChar)
|
|
{
|
|
baseBuild.append(WebDAVHelper.PathSeperatorChar);
|
|
}
|
|
String basePath = baseBuild.toString();
|
|
|
|
// Output the response for the root node, depth zero
|
|
generateResponseForNode(xml, pathNodeInfo, basePath);
|
|
|
|
// If additional levels are required and the root node is a folder then recurse to the required
|
|
// level and output node details a level at a time
|
|
if (getDepth() != WebDAV.DEPTH_0 && pathNodeInfo.isFolder())
|
|
{
|
|
// Create the initial list of nodes to report
|
|
List<FileInfo> nodeInfos = new ArrayList<FileInfo>(10);
|
|
nodeInfos.add(pathNodeInfo);
|
|
|
|
int curDepth = WebDAV.DEPTH_1;
|
|
|
|
// Save the base path length
|
|
int baseLen = baseBuild.length();
|
|
|
|
// List of next level of nodes to report
|
|
List<FileInfo> nextNodeInfos = null;
|
|
if (getDepth() > WebDAV.DEPTH_1)
|
|
{
|
|
nextNodeInfos = new ArrayList<FileInfo>(10);
|
|
}
|
|
|
|
// Loop reporting each level of nodes to the requested depth
|
|
while (curDepth <= getDepth() && nodeInfos != null)
|
|
{
|
|
// Clear out the next level of nodes, if required
|
|
if (nextNodeInfos != null)
|
|
{
|
|
nextNodeInfos.clear();
|
|
}
|
|
|
|
// Output the current level of node(s), the node list should
|
|
// only contain folder nodes
|
|
|
|
for (FileInfo curNodeInfo : nodeInfos)
|
|
{
|
|
// Get the list of child nodes for the current node
|
|
List<FileInfo> childNodeInfos = fileFolderService.list(curNodeInfo.getNodeRef());
|
|
|
|
// can skip the current node if it doesn't have children
|
|
if (childNodeInfos.size() == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Output the child node details
|
|
// Generate the base path for the current parent node
|
|
|
|
baseBuild.setLength(baseLen);
|
|
try
|
|
{
|
|
String pathSnippet = getDAVHelper().getPathFromNode(pathNodeInfo.getNodeRef(), curNodeInfo.getNodeRef());
|
|
baseBuild.append(pathSnippet);
|
|
}
|
|
catch (FileNotFoundException e)
|
|
{
|
|
// move to the next node
|
|
continue;
|
|
}
|
|
|
|
int curBaseLen = baseBuild.length();
|
|
|
|
// Output the child node details
|
|
for (FileInfo curChildInfo : childNodeInfos)
|
|
{
|
|
// Build the path for the current child node
|
|
baseBuild.setLength(curBaseLen);
|
|
|
|
baseBuild.append(curChildInfo.getName());
|
|
|
|
// Output the current child node details
|
|
generateResponseForNode(xml, curChildInfo, baseBuild.toString());
|
|
|
|
// If the child is a folder add it to the list of next level nodes
|
|
if (nextNodeInfos != null && curChildInfo.isFolder())
|
|
{
|
|
nextNodeInfos.add(curChildInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update the current tree depth
|
|
curDepth++;
|
|
|
|
// Move the next level of nodes to the current node list
|
|
nodeInfos = nextNodeInfos;
|
|
}
|
|
}
|
|
|
|
// Close the outer XML element
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_MULTI_STATUS, WebDAV.XML_NS_MULTI_STATUS);
|
|
|
|
// Send remaining data
|
|
xml.flush();
|
|
}
|
|
|
|
@Override
|
|
protected XMLWriter createXMLWriter() throws IOException
|
|
{
|
|
String userAgent = m_request.getHeader("User-Agent");
|
|
if ((null != userAgent) && userAgent.toLowerCase().startsWith("microsoft-webdav-miniredir/5.1."))
|
|
{
|
|
// ALF-9952: XP requires compact XML for this response
|
|
return new XMLWriter(m_response.getOutputStream(), OutputFormat.createCompactFormat());
|
|
}
|
|
else
|
|
{
|
|
return super.createXMLWriter();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a WebDAVProperty from the given XML node
|
|
*/
|
|
protected WebDAVProperty createProperty(Node node)
|
|
{
|
|
WebDAVProperty property = null;
|
|
|
|
String strName = node.getLocalName();
|
|
String strNamespaceUri = node.getNamespaceURI();
|
|
|
|
if (WebDAV.DEFAULT_NAMESPACE_URI.equals(strNamespaceUri))
|
|
{
|
|
property = new WebDAVProperty(strName);
|
|
}
|
|
else
|
|
{
|
|
property = new WebDAVProperty(strName, strNamespaceUri, getNamespaceName(strNamespaceUri));
|
|
}
|
|
|
|
return property;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the namespace name for the given namespace URI, one is
|
|
* generated if it doesn't exist
|
|
*/
|
|
private String getNamespaceName(String strNamespaceUri)
|
|
{
|
|
if (strNamespaceUri == null)
|
|
{
|
|
return null;
|
|
}
|
|
String strNamespaceName = m_namespaces.get(strNamespaceUri);
|
|
if (strNamespaceName == null)
|
|
{
|
|
strNamespaceName = "ns" + m_namespaces.size();
|
|
m_namespaces.put(strNamespaceUri, strNamespaceName);
|
|
}
|
|
|
|
return strNamespaceName;
|
|
}
|
|
|
|
/**
|
|
* Generates the required response XML for the current node
|
|
*
|
|
* @param xml XMLWriter
|
|
* @param node NodeRef
|
|
* @param path String
|
|
*/
|
|
protected void generateResponseForNode(XMLWriter xml, FileInfo nodeInfo, String path) throws Exception
|
|
{
|
|
boolean isFolder = nodeInfo.isFolder();
|
|
|
|
// Output the response block for the current node
|
|
xml.startElement(
|
|
WebDAV.DAV_NS,
|
|
WebDAV.XML_RESPONSE,
|
|
WebDAV.XML_NS_RESPONSE,
|
|
getDAVHelper().getNullAttributes());
|
|
|
|
// Build the href string for the current node
|
|
String strHRef = getURLForPath(m_request, path, isFolder);
|
|
|
|
if (nodeInfo.isLink())
|
|
{
|
|
Path pathToNode = getNodeService().getPath(nodeInfo.getLinkNodeRef());
|
|
if (pathToNode.size() > 2)
|
|
{
|
|
pathToNode = pathToNode.subPath(2, pathToNode.size() - 1);
|
|
}
|
|
|
|
String rootURL = getURLForPath(m_request, pathToNode.toDisplayPath(getNodeService(), getPermissionService()), true);
|
|
if (rootURL.endsWith(WebDAVHelper.PathSeperator) == false)
|
|
{
|
|
rootURL = rootURL + WebDAVHelper.PathSeperator;
|
|
}
|
|
|
|
String fname = (String) getNodeService().getProperty(nodeInfo.getLinkNodeRef(), ContentModel.PROP_NAME);
|
|
strHRef = rootURL + WebDAVHelper.encodeURL(fname, m_userAgent) + WebDAVHelper.PathSeperator;
|
|
isFolder = getFileFolderService().getFileInfo(nodeInfo.getLinkNodeRef()).isFolder();
|
|
}
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF, getDAVHelper().getNullAttributes());
|
|
xml.write(strHRef);
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF);
|
|
|
|
switch (m_mode)
|
|
{
|
|
case GET_NAMED_PROPS:
|
|
generateNamedPropertiesResponse(xml, nodeInfo, isFolder);
|
|
break;
|
|
case GET_ALL_PROPS:
|
|
generateAllPropertiesResponse(xml, nodeInfo, isFolder);
|
|
break;
|
|
case FIND_PROPS:
|
|
generateFindPropertiesResponse(xml, nodeInfo, isFolder);
|
|
break;
|
|
}
|
|
|
|
// Close off the response element
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_RESPONSE, WebDAV.XML_NS_RESPONSE);
|
|
}
|
|
|
|
/**
|
|
* Generates the XML response for a PROPFIND request that asks for a
|
|
* specific set of properties
|
|
*
|
|
* @param xml XMLWriter
|
|
* @param node NodeRef
|
|
* @param isDir boolean
|
|
*/
|
|
private void generateNamedPropertiesResponse(XMLWriter xml, FileInfo nodeInfo, boolean isDir) throws Exception
|
|
{
|
|
// Get the properties for the node
|
|
Map<QName, Serializable> props = nodeInfo.getProperties();
|
|
|
|
// Output the start of the properties element
|
|
Attributes nullAttr = getDAVHelper().getNullAttributes();
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT, nullAttr);
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP, nullAttr);
|
|
|
|
ArrayList<WebDAVProperty> propertiesNotFound = new ArrayList<WebDAVProperty>();
|
|
|
|
TypeConverter typeConv = DefaultTypeConverter.INSTANCE;
|
|
|
|
// Loop through the requested property list
|
|
for (WebDAVProperty property : m_properties)
|
|
{
|
|
// Get the requested property details
|
|
|
|
String propName = property.getName();
|
|
String propNamespaceUri = property.getNamespaceUri();
|
|
|
|
// Check if the property is a standard WebDAV property
|
|
|
|
Object davValue = null;
|
|
|
|
if (WebDAV.DEFAULT_NAMESPACE_URI.equals(propNamespaceUri))
|
|
{
|
|
// Check if the client is requesting lock information
|
|
if (propName.equals(WebDAV.XML_LOCK_DISCOVERY)) // && metaData.isLocked())
|
|
{
|
|
generateLockDiscoveryResponse(xml, nodeInfo, isDir);
|
|
}
|
|
else if (propName.equals(WebDAV.XML_SUPPORTED_LOCK))
|
|
{
|
|
// Output the supported lock types
|
|
writeLockTypes(xml);
|
|
}
|
|
|
|
// Check if the client is requesting the resource type
|
|
|
|
else if (propName.equals(WebDAV.XML_RESOURCE_TYPE))
|
|
{
|
|
// If the node is a folder then return as a collection type
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_RESOURCE_TYPE, WebDAV.XML_NS_RESOURCE_TYPE, nullAttr);
|
|
if (isDir)
|
|
{
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_COLLECTION));
|
|
}
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_RESOURCE_TYPE, WebDAV.XML_NS_RESOURCE_TYPE);
|
|
}
|
|
else if (propName.equals(WebDAV.XML_DISPLAYNAME))
|
|
{
|
|
// Get the node name
|
|
if (getRootNodeRef().equals(nodeInfo.getNodeRef()))
|
|
{
|
|
// Output an empty name for the root node
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_SOURCE));
|
|
}
|
|
else
|
|
{
|
|
// Get the node name
|
|
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_DISPLAYNAME);
|
|
|
|
// Output the node name
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_DISPLAYNAME, WebDAV.XML_NS_DISPLAYNAME, nullAttr);
|
|
if (davValue != null)
|
|
{
|
|
String name = typeConv.convert(String.class, davValue);
|
|
if (name == null || name.length() == 0)
|
|
{
|
|
logger.error("WebDAV name is null, value=" + davValue.getClass().getName() + ", node=" + nodeInfo.getNodeRef());
|
|
}
|
|
xml.write(name);
|
|
}
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_DISPLAYNAME, WebDAV.XML_NS_DISPLAYNAME);
|
|
}
|
|
}
|
|
else if (propName.equals(WebDAV.XML_SOURCE))
|
|
{
|
|
// NOTE: source is always a no content element in our
|
|
// implementation
|
|
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_SOURCE));
|
|
}
|
|
else if (propName.equals(WebDAV.XML_GET_LAST_MODIFIED))
|
|
{
|
|
// Get the modifed date/time
|
|
|
|
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_GET_LAST_MODIFIED);
|
|
|
|
// Output the last modified date of the node
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_LAST_MODIFIED, WebDAV.XML_NS_GET_LAST_MODIFIED,
|
|
nullAttr);
|
|
if (davValue != null)
|
|
xml.write(WebDAV.formatModifiedDate(typeConv.convert(Date.class, davValue)));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_LAST_MODIFIED, WebDAV.XML_NS_GET_LAST_MODIFIED);
|
|
}
|
|
else if (propName.equals(WebDAV.XML_GET_CONTENT_LANGUAGE) && !isDir)
|
|
{
|
|
// Get the content language
|
|
// TODO:
|
|
// Output the content language
|
|
xml.startElement(
|
|
WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LANGUAGE,
|
|
WebDAV.XML_NS_GET_CONTENT_LANGUAGE, nullAttr);
|
|
// TODO:
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LANGUAGE, WebDAV.XML_NS_GET_CONTENT_LANGUAGE);
|
|
}
|
|
else if (propName.equals(WebDAV.XML_GET_CONTENT_TYPE) && !isDir)
|
|
{
|
|
// Get the content type
|
|
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_GET_CONTENT_TYPE);
|
|
|
|
// Output the content type
|
|
xml.startElement(
|
|
WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_TYPE,
|
|
WebDAV.XML_NS_GET_CONTENT_TYPE, nullAttr);
|
|
if (davValue != null)
|
|
xml.write(typeConv.convert(String.class, davValue));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_TYPE, WebDAV.XML_NS_GET_CONTENT_TYPE);
|
|
}
|
|
else if (propName.equals(WebDAV.XML_GET_ETAG) && !isDir)
|
|
{
|
|
// Output the etag
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG, nullAttr);
|
|
xml.write(getDAVHelper().makeETag(nodeInfo));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG);
|
|
}
|
|
else if (propName.equals(WebDAV.XML_GET_CONTENT_LENGTH))
|
|
{
|
|
// Get the content length, if it's not a folder
|
|
long len = 0;
|
|
|
|
if (!isDir)
|
|
{
|
|
ContentData contentData = (ContentData) props.get(ContentModel.PROP_CONTENT);
|
|
if (contentData != null)
|
|
len = contentData.getSize();
|
|
}
|
|
|
|
// Output the content length
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LENGTH, WebDAV.XML_NS_GET_CONTENT_LENGTH,
|
|
nullAttr);
|
|
xml.write("" + len);
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LENGTH, WebDAV.XML_NS_GET_CONTENT_LENGTH);
|
|
}
|
|
else if (propName.equals(WebDAV.XML_CREATION_DATE))
|
|
{
|
|
// Get the creation date
|
|
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_CREATION_DATE);
|
|
|
|
// Output the creation date
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_CREATION_DATE, WebDAV.XML_NS_CREATION_DATE, nullAttr);
|
|
if (davValue != null)
|
|
xml.write(WebDAV.formatCreationDate(typeConv.convert(Date.class, davValue)));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_CREATION_DATE, WebDAV.XML_NS_CREATION_DATE);
|
|
}
|
|
else if ( propName.equals( WebDAV.XML_ALF_AUTHTICKET))
|
|
{
|
|
// Get the users authentication ticket
|
|
|
|
SessionUser davUser = (SessionUser) m_request.getSession().getAttribute( AuthenticationFilter.AUTHENTICATION_USER);
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_ALF_AUTHTICKET, WebDAV.XML_NS_ALF_AUTHTICKET, nullAttr);
|
|
if ( davUser != null)
|
|
xml.write( davUser.getTicket());
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_ALF_AUTHTICKET, WebDAV.XML_NS_ALF_AUTHTICKET);
|
|
}
|
|
else
|
|
{
|
|
// Could not map the requested property to an Alfresco property
|
|
if (property.getName().equals(WebDAV.XML_HREF) == false)
|
|
propertiesNotFound.add(property);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Look in the custom properties
|
|
|
|
// TODO: Custom properties lookup
|
|
// String qualifiedName = propNamespaceUri + WebDAV.NAMESPACE_SEPARATOR + propName;
|
|
|
|
String value = (String) nodeInfo.getProperties().get(property.createQName());
|
|
if (value == null)
|
|
{
|
|
propertiesNotFound.add(property);
|
|
}
|
|
else
|
|
{
|
|
if (property.hasNamespaceName())
|
|
{
|
|
xml.startElement(property.getNamespaceName(), property.getName(), property.getNamespaceName() + WebDAV.NAMESPACE_SEPARATOR + property.getName(), nullAttr);
|
|
xml.write(value);
|
|
xml.endElement(property.getNamespaceName(), property.getName(), property.getNamespaceName() + WebDAV.NAMESPACE_SEPARATOR + property.getName());
|
|
}
|
|
else
|
|
{
|
|
xml.startElement("", property.getName(), property.getName(), nullAttr);
|
|
xml.write(value);
|
|
xml.endElement("", property.getName(), property.getName());
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// Close off the successful part of the response
|
|
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP);
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS, nullAttr);
|
|
xml.write(WebDAV.HTTP1_1 + " " + HttpServletResponse.SC_OK + " " + WebDAV.SC_OK_DESC);
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS);
|
|
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT);
|
|
|
|
// If some of the requested properties were not found return another
|
|
// status section
|
|
|
|
if (propertiesNotFound.size() > 0)
|
|
{
|
|
// Start the second status section
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT, nullAttr);
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP, nullAttr);
|
|
|
|
// Loop through the list of properties that were not found
|
|
|
|
for (WebDAVProperty property : propertiesNotFound)
|
|
{
|
|
// Output the property not found status block
|
|
|
|
String propName = property.getName();
|
|
String propNamespaceName = property.getNamespaceName();
|
|
String propQName = propName;
|
|
if (propNamespaceName != null && propNamespaceName.length() > 0)
|
|
propQName = propNamespaceName + ":" + propName;
|
|
|
|
xml.write(DocumentHelper.createElement(propQName));
|
|
}
|
|
|
|
// Close the unsuccessful part of the response
|
|
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP);
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS, nullAttr);
|
|
xml.write(WebDAV.HTTP1_1 + " " + HttpServletResponse.SC_NOT_FOUND + " " + WebDAV.SC_NOT_FOUND_DESC);
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS);
|
|
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates the XML response for a PROPFIND request that asks for all known
|
|
* properties
|
|
*
|
|
* @param xml XMLWriter
|
|
* @param node NodeRef
|
|
* @param isDir boolean
|
|
*/
|
|
protected void generateAllPropertiesResponse(XMLWriter xml, FileInfo nodeInfo, boolean isDir) throws Exception
|
|
{
|
|
// Get the properties for the node
|
|
|
|
Map<QName, Serializable> props = nodeInfo.getProperties();
|
|
|
|
// Output the start of the properties element
|
|
|
|
Attributes nullAttr = getDAVHelper().getNullAttributes();
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT, nullAttr);
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP, nullAttr);
|
|
|
|
// Generate a lock status report, if locked
|
|
|
|
generateLockDiscoveryResponse(xml, nodeInfo, isDir);
|
|
|
|
// Output the supported lock types
|
|
|
|
writeLockTypes(xml);
|
|
|
|
// If the node is a folder then return as a collection type
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_RESOURCE_TYPE, WebDAV.XML_NS_RESOURCE_TYPE, nullAttr);
|
|
if (isDir)
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_COLLECTION));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_RESOURCE_TYPE, WebDAV.XML_NS_RESOURCE_TYPE);
|
|
|
|
// Get the node name
|
|
|
|
Object davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_DISPLAYNAME);
|
|
|
|
TypeConverter typeConv = DefaultTypeConverter.INSTANCE;
|
|
|
|
// Output the node name
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_DISPLAYNAME, WebDAV.XML_NS_DISPLAYNAME, nullAttr);
|
|
if (davValue != null)
|
|
{
|
|
String name = typeConv.convert(String.class, davValue);
|
|
if (name == null || name.length() == 0)
|
|
{
|
|
logger.error("WebDAV name is null, value=" + davValue.getClass().getName() + ", node=" + nodeInfo.getNodeRef());
|
|
}
|
|
xml.write(name);
|
|
}
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_DISPLAYNAME, WebDAV.XML_NS_DISPLAYNAME);
|
|
|
|
// Output the source
|
|
//
|
|
// NOTE: source is always a no content element in our implementation
|
|
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_SOURCE));
|
|
|
|
// Get the creation date
|
|
|
|
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_CREATION_DATE);
|
|
|
|
// Output the creation date
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_CREATION_DATE, WebDAV.XML_NS_CREATION_DATE, nullAttr);
|
|
if (davValue != null)
|
|
xml.write(WebDAV.formatCreationDate(typeConv.convert(Date.class, davValue)));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_CREATION_DATE, WebDAV.XML_NS_CREATION_DATE);
|
|
|
|
// Get the modifed date/time
|
|
|
|
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_GET_LAST_MODIFIED);
|
|
|
|
// Output the last modified date of the node
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_LAST_MODIFIED, WebDAV.XML_NS_GET_LAST_MODIFIED, nullAttr);
|
|
if (davValue != null)
|
|
xml.write(WebDAV.formatModifiedDate(typeConv.convert(Date.class, davValue)));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_LAST_MODIFIED, WebDAV.XML_NS_GET_LAST_MODIFIED);
|
|
|
|
// For a file node output the content language and content type
|
|
|
|
if (isDir == false)
|
|
{
|
|
// Get the content language
|
|
|
|
// TODO:
|
|
// Output the content language
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LANGUAGE, WebDAV.XML_NS_GET_CONTENT_LANGUAGE,
|
|
nullAttr);
|
|
// TODO:
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LANGUAGE, WebDAV.XML_NS_GET_CONTENT_LANGUAGE);
|
|
|
|
// Get the content type
|
|
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_GET_CONTENT_TYPE);
|
|
|
|
// Output the content type
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_TYPE, WebDAV.XML_NS_GET_CONTENT_TYPE, nullAttr);
|
|
if (davValue != null)
|
|
xml.write(typeConv.convert(String.class, davValue));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_TYPE, WebDAV.XML_NS_GET_CONTENT_TYPE);
|
|
|
|
// Output the etag
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG, nullAttr);
|
|
xml.write(getDAVHelper().makeETag(nodeInfo));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG);
|
|
}
|
|
|
|
// Get the content length, if it's not a folder
|
|
|
|
long len = 0;
|
|
|
|
if (isDir == false)
|
|
{
|
|
ContentData contentData = (ContentData) props.get(ContentModel.PROP_CONTENT);
|
|
if (contentData != null)
|
|
len = contentData.getSize();
|
|
}
|
|
|
|
// Output the content length
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LENGTH, WebDAV.XML_NS_GET_CONTENT_LENGTH, nullAttr);
|
|
xml.write("" + len);
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LENGTH, WebDAV.XML_NS_GET_CONTENT_LENGTH);
|
|
|
|
// Print out all the custom properties
|
|
|
|
SessionUser davUser = (SessionUser) m_request.getSession().getAttribute( AuthenticationFilter.AUTHENTICATION_USER);
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_ALF_AUTHTICKET, WebDAV.XML_NS_ALF_AUTHTICKET, nullAttr);
|
|
if ( davUser != null)
|
|
xml.write( davUser.getTicket());
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_ALF_AUTHTICKET, WebDAV.XML_NS_ALF_AUTHTICKET);
|
|
|
|
// Close off the response
|
|
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP);
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS, nullAttr);
|
|
xml.write(WebDAV.HTTP1_1 + " " + HttpServletResponse.SC_OK + " " + WebDAV.SC_OK_DESC);
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS);
|
|
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT);
|
|
}
|
|
|
|
/**
|
|
* Generates the XML response for a PROPFIND request that asks for a list of
|
|
* all known properties
|
|
*
|
|
* @param xml XMLWriter
|
|
* @param node NodeRef
|
|
* @param isDir boolean
|
|
*/
|
|
protected void generateFindPropertiesResponse(XMLWriter xml, FileInfo nodeInfo, boolean isDir)
|
|
{
|
|
try
|
|
{
|
|
// Output the start of the properties element
|
|
|
|
Attributes nullAttr = getDAVHelper().getNullAttributes();
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT, nullAttr);
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP, nullAttr);
|
|
|
|
// Output the well-known properties
|
|
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_LOCK_DISCOVERY));
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_SUPPORTED_LOCK));
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_RESOURCE_TYPE));
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_DISPLAYNAME));
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_GET_LAST_MODIFIED));
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_GET_CONTENT_LENGTH));
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_CREATION_DATE));
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_GET_ETAG));
|
|
|
|
if (isDir)
|
|
{
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_GET_CONTENT_LANGUAGE));
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_GET_CONTENT_TYPE));
|
|
}
|
|
|
|
// Output the custom properties
|
|
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_ALF_AUTHTICKET));
|
|
|
|
// Close off the response
|
|
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP);
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS, nullAttr);
|
|
xml.write(WebDAV.HTTP1_1 + " " + HttpServletResponse.SC_OK + " " + WebDAV.SC_OK_DESC);
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS);
|
|
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Convert to a runtime exception
|
|
|
|
throw new AlfrescoRuntimeException("XML processing error", ex);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates the XML response snippet showing the lock information for the
|
|
* given path
|
|
*
|
|
* @param xml XMLWriter
|
|
* @param node NodeRef
|
|
* @param isDir boolean
|
|
*/
|
|
protected void generateLockDiscoveryResponse(XMLWriter xml, FileInfo nodeInfo, boolean isDir) throws Exception
|
|
{
|
|
// Output the lock status response
|
|
|
|
LockInfo lockInfo = getNodeLockInfo(nodeInfo);
|
|
if (lockInfo.isLocked())
|
|
{
|
|
generateLockDiscoveryXML(xml, nodeInfo, lockInfo);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Output the supported lock types XML element
|
|
*
|
|
* @param xml XMLWriter
|
|
*/
|
|
protected void writeLockTypes(XMLWriter xml)
|
|
{
|
|
try
|
|
{
|
|
AttributesImpl nullAttr = getDAVHelper().getNullAttributes();
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_SUPPORTED_LOCK, WebDAV.XML_NS_SUPPORTED_LOCK, nullAttr);
|
|
|
|
// Output exclusive lock
|
|
writeLock(xml, WebDAV.XML_NS_EXCLUSIVE);
|
|
// Output shared lock
|
|
writeLock(xml, WebDAV.XML_NS_SHARED);
|
|
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_SUPPORTED_LOCK, WebDAV.XML_NS_SUPPORTED_LOCK);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new AlfrescoRuntimeException("XML write error", ex);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Output the lockentry element of the specified type
|
|
* @param xml XMLWriter
|
|
* @param lockType lock type. Can be WebDAV.XML_NS_EXCLUSIVE or WebDAV.XML_NS_SHARED
|
|
* @param lockType lock type containing namespace
|
|
* @throws SAXException
|
|
* @throws IOException
|
|
*/
|
|
private void writeLock(XMLWriter xml, String lockType) throws SAXException, IOException
|
|
{
|
|
AttributesImpl nullAttr = getDAVHelper().getNullAttributes();
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_ENTRY, WebDAV.XML_NS_LOCK_ENTRY, nullAttr);
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE, nullAttr);
|
|
xml.write(DocumentHelper.createElement(lockType));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE);
|
|
|
|
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE, nullAttr);
|
|
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_WRITE));
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE);
|
|
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_ENTRY, WebDAV.XML_NS_LOCK_ENTRY);
|
|
}
|
|
}
|