/* * ==================================================================== * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://svnkit.com/license.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * ==================================================================== */ package org.tmatesoft.svn.core.internal.server.dav.handlers; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNProperties; import org.tmatesoft.svn.core.SVNProperty; import org.tmatesoft.svn.core.SVNPropertyValue; import org.tmatesoft.svn.core.internal.io.dav.DAVElement; import org.tmatesoft.svn.core.internal.io.fs.FSRevisionRoot; import org.tmatesoft.svn.core.internal.server.dav.DAVConfig; import org.tmatesoft.svn.core.internal.server.dav.DAVDepth; import org.tmatesoft.svn.core.internal.server.dav.DAVException; import org.tmatesoft.svn.core.internal.server.dav.DAVLock; import org.tmatesoft.svn.core.internal.server.dav.DAVLockScope; import org.tmatesoft.svn.core.internal.server.dav.DAVPathUtil; import org.tmatesoft.svn.core.internal.server.dav.DAVRepositoryManager; import org.tmatesoft.svn.core.internal.server.dav.DAVResource; import org.tmatesoft.svn.core.internal.server.dav.DAVResourceKind; import org.tmatesoft.svn.core.internal.server.dav.DAVResourceState; import org.tmatesoft.svn.core.internal.server.dav.DAVResourceType; import org.tmatesoft.svn.core.internal.server.dav.DAVResourceURI; import org.tmatesoft.svn.core.internal.server.dav.DAVServlet; import org.tmatesoft.svn.core.internal.server.dav.DAVServletUtil; import org.tmatesoft.svn.core.internal.server.dav.DAVXMLUtil; import org.tmatesoft.svn.core.internal.util.SVNDate; import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil; import org.tmatesoft.svn.core.internal.util.SVNXMLUtil; import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; import org.tmatesoft.svn.core.internal.wc.SVNPropertiesManager; import org.tmatesoft.svn.util.SVNLogType; /** * @author TMate Software Ltd. * @version 1.2.0 */ public class DAVPropfindHandler extends ServletDAVHandler implements IDAVResourceWalkHandler { public static final List NAMESPACES = new LinkedList(); static { NAMESPACES.add(DAVElement.DAV_NAMESPACE); NAMESPACES.add(DAVElement.SVN_DAV_PROPERTY_NAMESPACE); } private static final String DEFAULT_AUTOVERSION_LINE = "DAV:checkout-checkin"; private DAVPropfindRequest myDAVRequest; private boolean myIsAllProp; //private boolean myIsPropName; private boolean myIsProp; private DAVElementProperty myDocRoot; private StringBuffer myPropStat404; private StringBuffer myResponseBuffer; private DAVLockInfoProvider myLocksProvider; public DAVPropfindHandler(DAVRepositoryManager connector, HttpServletRequest request, HttpServletResponse response) { super(connector, request, response); } protected DAVRequest getDAVRequest() { return getPropfindRequest(); } public void execute() throws SVNException { DAVResource resource = getRequestedDAVResource(true, false); DAVResourceState resourceState = getResourceState(resource); if (resourceState == DAVResourceState.NULL) { //TODO: what body should we send? sendError(HttpServletResponse.SC_NOT_FOUND, null); return; } DAVDepth depth = getRequestDepth(DAVDepth.DEPTH_INFINITY); //TODO: check the depth is not less than 0; if it is, send BAD_REQUEST if (depth == DAVDepth.DEPTH_INFINITY && resource.isCollection()) { DAVConfig config = getConfig(); if (!config.isAllowDepthInfinity()) { String message = "PROPFIND requests with a Depth of \"infinity\" are not allowed for " + SVNEncodingUtil.xmlEncodeCDATA(getURI()) + "."; response(message, DAVServlet.getStatusLine(HttpServletResponse.SC_FORBIDDEN), HttpServletResponse.SC_FORBIDDEN); return; } } long readCount = readInput(false); DAVPropfindRequest request = getPropfindRequest(); DAVElementProperty rootElement = request.getRootElement(); if (readCount > 0 && rootElement.getName() != DAVElement.PROPFIND) { //TODO: maybe add logging here later //TODO: what body should we send? sendError(HttpServletResponse.SC_BAD_REQUEST, null); return; } myIsAllProp = false; //myIsPropName = false; myIsProp = false; if (readCount == 0 || rootElement.hasChild(DAVElement.ALLPROP)) { myIsAllProp = true; } else if (rootElement.hasChild(DAVElement.PROPNAME)) { //myIsPropName = true; } else if (rootElement.hasChild(DAVElement.PROP)) { myIsProp = true; } else { //TODO: what body should we send? //TODO: maybe add logging here later setResponseStatus(HttpServletResponse.SC_BAD_REQUEST); return; } myLocksProvider = null; try { myLocksProvider = DAVLockInfoProvider.createLockInfoProvider(this, false); } catch (SVNException svne) { throw DAVException.convertError(svne.getErrorMessage(), HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "The lock database could not be opened, preventing access to the various lock properties for the PROPFIND.", null); } myResponseBuffer = new StringBuffer(); DAVXMLUtil.beginMultiStatus(getHttpServletResponse(), SC_MULTISTATUS, getNamespaces(), myResponseBuffer); int walkType = DAVResourceWalker.DAV_WALKTYPE_NORMAL | DAVResourceWalker.DAV_WALKTYPE_AUTH | DAVResourceWalker.DAV_WALKTYPE_LOCKNULL; DAVResourceWalker walker = new DAVResourceWalker(); DAVException error = null; try { walker.walk(myLocksProvider, resource, null, 0, null, walkType, this, depth); } catch (DAVException dave) { error = dave; } if (error != null) { throw new DAVException("Provider encountered an error while streaming", error.getResponseCode(), error, 0); } SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.MULTISTATUS.getName(), myResponseBuffer); String responseBody = myResponseBuffer.toString(); try { setResponseContentLength(responseBody.getBytes(UTF8_ENCODING).length); } catch (UnsupportedEncodingException e) { setResponseContentLength(responseBody.getBytes().length); } setResponseStatus(SC_MULTISTATUS); try { getResponseWriter().write(responseBody); } catch (IOException e) { SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED, e), e, SVNLogType.NETWORK); } } public DAVResponse handleResource(DAVResponse response, DAVResource resource, DAVLockInfoProvider lockInfoProvider, LinkedList ifHeaders, int flags, DAVLockScope lockScope, CallType callType) throws DAVException { DAVPropertiesProvider propsProvider = null; try { propsProvider = DAVPropertiesProvider.createPropertiesProvider(resource, this); } catch (DAVException dave) { if (myIsProp) { cacheBadProps(); DAVPropsResult badProps = new DAVPropsResult(); badProps.addPropStatsText(myPropStat404.toString()); streamResponse(resource, 0, badProps); } else { streamResponse(resource, HttpServletResponse.SC_OK, null); } return null; } DAVPropsResult result = null; if (myIsProp) { result = getProps(propsProvider, getPropfindRequest().getRootElement()); } else { DAVInsertPropAction action = myIsAllProp ? DAVInsertPropAction.INSERT_VALUE : DAVInsertPropAction.INSERT_NAME; result = getAllProps(propsProvider, action); } streamResponse(resource, 0, result); return null; } private DAVPropsResult getAllProps(DAVPropertiesProvider propsProvider, DAVInsertPropAction action) throws DAVException { boolean foundContentType = false; boolean foundContentLang = false; DAVPropsResult result = new DAVPropsResult(); StringBuffer buffer = new StringBuffer(); if (action != DAVInsertPropAction.INSERT_SUPPORTED) { if (propsProvider.isDeferred()) { propsProvider.open(true); } SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROPSTAT.getName(), SVNXMLUtil.XML_STYLE_NORMAL, null, buffer); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROP.getName(), SVNXMLUtil.XML_STYLE_NORMAL, null, buffer); Map namespacesToPrefixes = new HashMap(); propsProvider.defineNamespaces(namespacesToPrefixes); Collection propNames = propsProvider.getPropertyNames(); int ind = 0; for (Iterator propNamesIter = propNames.iterator(); propNamesIter.hasNext();) { DAVElement propNameElement = (DAVElement) propNamesIter.next(); if (DAVElement.DAV_NAMESPACE.equals(propNameElement.getNamespace())) { if (DAVElement.GET_CONTENT_TYPE.getName().equals(propNameElement.getName())) { foundContentType = true; } else if (DAVElement.GET_CONTENT_LANGUAGE.getName().equals(propNameElement.getName())) { foundContentLang = true; } } if (action == DAVInsertPropAction.INSERT_VALUE) { try { propsProvider.outputValue(propNameElement, buffer); } catch (DAVException dave) { //TODO: probably change this behavior in future continue; } } else { ind = outputPropName(propNameElement, namespacesToPrefixes, ind, buffer); } } generateXMLNSNamespaces(result, namespacesToPrefixes); } addAllLivePropNamespaces(result); insertAllLiveProps(propsProvider.getResource(), action, buffer); LivePropertySpecification suppLockSpec = (LivePropertySpecification) OUR_CORE_LIVE_PROPS.get(DAVElement.SUPPORTED_LOCK); insertCoreLiveProperty(propsProvider.getResource(), action, suppLockSpec, buffer); LivePropertySpecification lockDiscoverySpec = (LivePropertySpecification) OUR_CORE_LIVE_PROPS.get(DAVElement.LOCK_DISCOVERY); insertCoreLiveProperty(propsProvider.getResource(), action, lockDiscoverySpec, buffer); if (!foundContentType) { LivePropertySpecification getContentTypeSpec = (LivePropertySpecification) OUR_CORE_LIVE_PROPS.get(DAVElement.GET_CONTENT_TYPE); insertCoreLiveProperty(propsProvider.getResource(), action, getContentTypeSpec, buffer); } if (!foundContentLang) { LivePropertySpecification getContentLanguageSpec = (LivePropertySpecification) OUR_CORE_LIVE_PROPS.get(DAVElement.GET_CONTENT_LANGUAGE); insertCoreLiveProperty(propsProvider.getResource(), action, getContentLanguageSpec, buffer); } if (action != DAVInsertPropAction.INSERT_SUPPORTED) { SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROP.getName(), buffer); SVNXMLUtil.openCDataTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.STATUS.getName(), "HTTP/1.1 200 OK", null, false, false, buffer); SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROPSTAT.getName(), buffer); } result.addPropStatsText(buffer.toString()); return result; } private void insertAllLiveProps(DAVResource resource, DAVInsertPropAction propAction, StringBuffer buffer) throws DAVException { if (!resource.exists()) { return; } for (Iterator livePropsIter = OUR_LIVE_PROPS.keySet().iterator(); livePropsIter.hasNext();) { DAVElement propElement = (DAVElement) livePropsIter.next(); if (propElement == DAVElement.COMMENT || propElement == DAVElement.DISPLAY_NAME || propElement == DAVElement.SOURCE) { //only RESOURCETYPE core prop should be inserted continue; } LivePropertySpecification lps = (LivePropertySpecification) OUR_LIVE_PROPS.get(propElement); insertLiveProp(resource, lps, propAction, buffer); } } private DAVPropsResult getProps(DAVPropertiesProvider propsProvider, DAVElementProperty docRootElement) throws DAVException { StringBuffer buffer = new StringBuffer(); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROPSTAT.getName(), SVNXMLUtil.XML_STYLE_NORMAL, null, buffer); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROP.getName(), SVNXMLUtil.XML_STYLE_NORMAL, null, buffer); StringBuffer badRes = null; Collection xmlnses = new LinkedList(); boolean haveGood = false; boolean definedNamespaces = false; Map namespacesToPrefixes = new HashMap(); int prefixInd = 0; DAVElementProperty propElement = docRootElement.getChild(DAVElement.PROP); List childrenElements = propElement.getChildren(); boolean filledNamespaces = false; for (Iterator childrenIter = childrenElements.iterator(); childrenIter.hasNext();) { DAVElementProperty childElement = (DAVElementProperty) childrenIter.next(); LivePropertySpecification livePropSpec = findLiveProperty(childElement.getName()); if (livePropSpec != null) { DAVInsertPropAction doneAction = insertLiveProp(propsProvider.getResource(), livePropSpec, DAVInsertPropAction.INSERT_VALUE, buffer); if (doneAction == DAVInsertPropAction.INSERT_VALUE) { haveGood = true; if (!filledNamespaces) { int ind = 0; for (Iterator namespacesIter = NAMESPACES.iterator(); namespacesIter.hasNext();) { String namespace = (String) namespacesIter.next(); String xmlns = " xmlns:lp" + ind + "=\"" + namespace + "\""; xmlnses.add(xmlns); ind++; } filledNamespaces = true; } continue; } } if (propsProvider.isDeferred()) { propsProvider.open(true); } boolean found = false; try { found = propsProvider.outputValue(childElement.getName(), buffer); } catch (DAVException dave) { continue; } if (found) { haveGood = true; if (!definedNamespaces) { propsProvider.defineNamespaces(namespacesToPrefixes); definedNamespaces = true; } continue; } if (badRes == null) { badRes = new StringBuffer(); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROPSTAT.getName(), SVNXMLUtil.XML_STYLE_NORMAL, null, badRes); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROP.getName(), SVNXMLUtil.XML_STYLE_NORMAL, null, badRes); } prefixInd = outputPropName(childElement.getName(), namespacesToPrefixes, prefixInd, buffer); } SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROP.getName(), buffer); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.STATUS.getName(), SVNXMLUtil.XML_STYLE_PROTECT_CDATA, null, buffer); buffer.append("HTTP/1.1 200 OK"); SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.STATUS.getName(), buffer); SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROPSTAT.getName(), buffer); DAVPropsResult result = new DAVPropsResult(); if (badRes != null) { SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROP.getName(), badRes); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.STATUS.getName(), SVNXMLUtil.XML_STYLE_PROTECT_CDATA, null, badRes); badRes.append("HTTP/1.1 404 Not Found"); SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.STATUS.getName(), badRes); SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROPSTAT.getName(), badRes); if (!haveGood) { result.addPropStatsText(badRes.toString()); } else { result.addPropStatsText(buffer.toString()); result.addPropStatsText(badRes.toString()); } } else { result.addPropStatsText(buffer.toString()); } addNamespaces(result, xmlnses); generateXMLNSNamespaces(result, namespacesToPrefixes); return result; } private void addNamespaces(DAVPropsResult result, Collection xmlnses) { for (Iterator xmlnsesIter = xmlnses.iterator(); xmlnsesIter.hasNext();) { String xmlnsString = (String) xmlnsesIter.next(); result.addNamespace(xmlnsString); } } private void addAllLivePropNamespaces(DAVPropsResult result) { for (Iterator namespacesIter = NAMESPACES.iterator(); namespacesIter.hasNext();) { String namespace = (String) namespacesIter.next(); int ind = NAMESPACES.indexOf(namespace); String xmlnsStr = " xmlns:lp" + ind + "=\"" + namespace + "\""; result.addNamespace(xmlnsStr); } } private void generateXMLNSNamespaces(DAVPropsResult result, Map namespacesToPrefixes) { for (Iterator prefixesIter = namespacesToPrefixes.keySet().iterator(); prefixesIter.hasNext();) { String uri = (String) prefixesIter.next(); String prefix = (String) namespacesToPrefixes.get(uri); result.addNamespace(" xmlns:" + prefix + "=\"" + uri + "\""); } } private int outputPropName(DAVElement propName, Map namespacesToPrefixes, int ind, StringBuffer buffer) { if ("".equals(propName.getNamespace())) { SVNXMLUtil.openXMLTag(null, propName.getName(), SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, buffer); } else { String prefix = namespacesToPrefixes != null ? (String) namespacesToPrefixes.get(propName.getNamespace()) : null; if (prefix == null) { prefix = "g" + ind; namespacesToPrefixes.put(propName.getNamespace(), prefix); } SVNXMLUtil.openXMLTag((String) namespacesToPrefixes.get(propName.getNamespace()), propName.getName(), SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, buffer); } return ++ind; } private DAVInsertPropAction insertCoreLiveProperty(DAVResource resource, DAVInsertPropAction propAction, LivePropertySpecification livePropSpec, StringBuffer buffer) throws DAVException { DAVInsertPropAction inserted = DAVInsertPropAction.NOT_DEF; DAVElement livePropElement = livePropSpec.getPropertyName(); String value = null; if (livePropElement == DAVElement.LOCK_DISCOVERY) { if (myLocksProvider != null) { DAVLock lock = null; try { lock = myLocksProvider.getLock(resource); } catch (DAVException dave) { throw new DAVException("DAV:lockdiscovery could not be determined due to a problem fetching the locks for this resource.", dave.getResponseCode(), dave, 0); } if (lock == null) { value = ""; } else { value = DAVLockInfoProvider.getActiveLockXML(lock); } } } else if (livePropElement == DAVElement.SUPPORTED_LOCK) { if (myLocksProvider != null) { value = myLocksProvider.getSupportedLock(resource); } } else if (livePropElement == DAVElement.GET_CONTENT_TYPE) { //TODO: get content type from a response when imitating a GET request? } else if (livePropElement == DAVElement.GET_CONTENT_LANGUAGE) { //TODO: get Content-Language from a response when imitating a GET request? } if (value != null) { if (propAction == DAVInsertPropAction.INSERT_SUPPORTED) { SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.SUPPORTED_LIVE_PROPERTY.getName(), SVNXMLUtil.XML_STYLE_NORMAL, "D:name", livePropElement.getName(), buffer); } else if (propAction == DAVInsertPropAction.INSERT_VALUE && !"".equals(value)) { SVNXMLUtil.openCDataTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, livePropElement.getName(), value, null, false, false, buffer); } else { SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, livePropElement.getName(), SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, buffer); } inserted = propAction; } return inserted; } private DAVInsertPropAction insertLiveProp(DAVResource resource, LivePropertySpecification livePropSpec, DAVInsertPropAction propAction, StringBuffer buffer) throws DAVException { if (!livePropSpec.isSVNSupported()) { //this is a core WebDAV live prop return insertCoreLiveProperty(resource, propAction, livePropSpec, buffer); } DAVElement livePropElement = livePropSpec.getPropertyName(); if (!resource.exists() && livePropElement != DAVElement.VERSION_CONTROLLED_CONFIGURATION && livePropElement != DAVElement.BASELINE_RELATIVE_PATH) { return DAVInsertPropAction.NOT_SUPP; } String value = null; DAVResourceURI uri = resource.getResourceURI(); if (livePropElement == DAVElement.GET_LAST_MODIFIED || livePropElement == DAVElement.CREATION_DATE) { if (resource.getType() == DAVResourceType.PRIVATE && resource.getKind() == DAVResourceKind.VCC) { return DAVInsertPropAction.NOT_SUPP; } if (livePropElement == DAVElement.CREATION_DATE) { try { value = SVNDate.formatDate(getLastModifiedTime2(resource)); } catch (SVNException svne) { return DAVInsertPropAction.NOT_DEF; } } else if (livePropElement == DAVElement.GET_LAST_MODIFIED) { try { value = SVNDate.formatRFC1123Date(getLastModifiedTime2(resource)); } catch (SVNException svne) { return DAVInsertPropAction.NOT_DEF; } } value = SVNEncodingUtil.xmlEncodeCDATA(value, true); } else if (livePropElement == DAVElement.CREATOR_DISPLAY_NAME) { if (resource.getType() == DAVResourceType.PRIVATE && resource.getKind() == DAVResourceKind.VCC) { return DAVInsertPropAction.NOT_SUPP; } long committedRev = -1; if (resource.isBaseLined() && resource.getType() == DAVResourceType.VERSION) { committedRev = resource.getRevision(); } else if (resource.getType() == DAVResourceType.REGULAR || resource.getType() == DAVResourceType.WORKING || resource.getType() == DAVResourceType.VERSION) { try { committedRev = resource.getCreatedRevisionUsingFS(null); } catch (SVNException svne) { value = "###error###"; } } else { return DAVInsertPropAction.NOT_SUPP; } String lastAuthor = null; try { lastAuthor = resource.getAuthor(committedRev); } catch (SVNException svne) { value = "###error###"; } if (lastAuthor == null) { return DAVInsertPropAction.NOT_DEF; } value = SVNEncodingUtil.xmlEncodeCDATA(lastAuthor, true); } else if (livePropElement == DAVElement.GET_CONTENT_LANGUAGE) { return DAVInsertPropAction.NOT_SUPP; } else if (livePropElement == DAVElement.GET_CONTENT_LENGTH) { if (resource.isCollection() || resource.isBaseLined()) { return DAVInsertPropAction.NOT_SUPP; } long fileSize = 0; try { fileSize = resource.getContentLength(null); value = String.valueOf(fileSize); } catch (SVNException e) { value = "0"; } } else if (livePropElement == DAVElement.GET_CONTENT_TYPE) { if (resource.isBaseLined() && resource.getType() == DAVResourceType.VERSION) { return DAVInsertPropAction.NOT_SUPP; } if (resource.getType() == DAVResourceType.PRIVATE && resource.getKind() == DAVResourceKind.VCC) { return DAVInsertPropAction.NOT_SUPP; } if (resource.isCollection()) { value = DAVResource.DEFAULT_COLLECTION_CONTENT_TYPE; } else { SVNPropertyValue contentType = null; try { contentType = resource.getProperty(null, SVNProperty.MIME_TYPE); } catch (SVNException svne) { // } if (contentType != null) { value = contentType.getString(); } else if (!resource.isSVNClient() && getRequest().getContentType() != null) { value = getRequest().getContentType(); } else { value = DAVResource.DEFAULT_FILE_CONTENT_TYPE; } try { SVNPropertiesManager.validateMimeType(value); } catch (SVNException svne) { return DAVInsertPropAction.NOT_DEF; } } } else if (livePropElement == DAVElement.GET_ETAG) { if (resource.getType() == DAVResourceType.PRIVATE && resource.getKind() == DAVResourceKind.VCC) { return DAVInsertPropAction.NOT_SUPP; } value = resource.getETag(); } else if (livePropElement == DAVElement.AUTO_VERSION) { if (getConfig().isAutoVersioning()) { value = DEFAULT_AUTOVERSION_LINE; } else { return DAVInsertPropAction.NOT_DEF; } } else if (livePropElement == DAVElement.BASELINE_COLLECTION) { if (resource.getType() != DAVResourceType.VERSION || !resource.isBaseLined()) { return DAVInsertPropAction.NOT_SUPP; } value = DAVPathUtil.buildURI(uri.getContext(), DAVResourceKind.BASELINE_COLL, resource.getRevision(), null, true); } else if (livePropElement == DAVElement.CHECKED_IN) { String s = null; if (resource.getType() == DAVResourceType.PRIVATE && resource.getKind() == DAVResourceKind.VCC) { long revNum = -1; try { revNum = resource.getLatestRevision(); s = DAVPathUtil.buildURI(uri.getContext(), DAVResourceKind.BASELINE, revNum, null, false); StringBuffer buf = SVNXMLUtil.openCDataTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.HREF.getName(), s, null, true, true, null); value = buf.toString(); } catch (SVNException svne) { value = "###error###"; } } else if (resource.getType() != DAVResourceType.REGULAR) { return DAVInsertPropAction.NOT_SUPP; } else { long revToUse = DAVServletUtil.getSafeCreatedRevision((FSRevisionRoot) resource.getRoot(), uri.getPath()); s = DAVPathUtil.buildURI(uri.getContext(), DAVResourceKind.VERSION, revToUse, uri.getPath(), false); StringBuffer buf = SVNXMLUtil.openCDataTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.HREF.getName(), s, null, true, true, null); value = buf.toString(); } } else if (livePropElement == DAVElement.VERSION_CONTROLLED_CONFIGURATION) { if (resource.getType() != DAVResourceType.REGULAR) { return DAVInsertPropAction.NOT_SUPP; } value = DAVPathUtil.buildURI(uri.getContext(), DAVResourceKind.VCC, -1, null, true); } else if (livePropElement == DAVElement.VERSION_NAME) { if (resource.getType() != DAVResourceType.VERSION && !resource.isVersioned()) { return DAVInsertPropAction.NOT_SUPP; } if (resource.getType() == DAVResourceType.PRIVATE && resource.getKind() == DAVResourceKind.VCC) { return DAVInsertPropAction.NOT_SUPP; } if (resource.isBaseLined()) { value = String.valueOf(resource.getRevision()); } else { try { long committedRev = resource.getCreatedRevisionUsingFS(null); value = String.valueOf(committedRev); value = SVNEncodingUtil.xmlEncodeCDATA(value, true); } catch (SVNException svne) { value = "###error###"; } } } else if (livePropElement == DAVElement.BASELINE_RELATIVE_PATH) { if (resource.getType() != DAVResourceType.REGULAR) { return DAVInsertPropAction.NOT_SUPP; } value = SVNEncodingUtil.xmlEncodeCDATA(DAVPathUtil.dropLeadingSlash(uri.getPath()), true); } else if (livePropElement == DAVElement.MD5_CHECKSUM) { if (!resource.isCollection() && !resource.isBaseLined() && (resource.getType() == DAVResourceType.REGULAR || resource.getType() == DAVResourceType.VERSION || resource.getType() == DAVResourceType.WORKING)) { try { value = resource.getMD5Checksum(null); if (value == null) { return DAVInsertPropAction.NOT_SUPP; } } catch (SVNException svne) { value = "###error###"; } } else { return DAVInsertPropAction.NOT_SUPP; } } else if (livePropElement == DAVElement.REPOSITORY_UUID) { try { value = resource.getRepositoryUUID(false); } catch (SVNException svne) { value = "###error###"; } } else if (livePropElement == DAVElement.DEADPROP_COUNT) { if (resource.getType() != DAVResourceType.REGULAR) { return DAVInsertPropAction.NOT_SUPP; } SVNProperties props = null; try { props = resource.getSVNProperties(null); int deadPropertiesCount = props.size(); value = String.valueOf(deadPropertiesCount); } catch (SVNException svne) { value = "###error###"; } } else if (livePropElement == DAVElement.RESOURCE_TYPE) { if (resource.getType() == DAVResourceType.VERSION) { if (resource.isBaseLined()) { StringBuffer buf = SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.BASELINE.getName(), SVNXMLUtil.XML_STYLE_SELF_CLOSING | SVNXMLUtil.XML_STYLE_PROTECT_CDATA, null, null); value = buf.toString(); } } else if (resource.getType() == DAVResourceType.REGULAR || resource.getType() == DAVResourceType.WORKING) { if (resource.isCollection()) { StringBuffer buf = SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.COLLECTION.getName(), SVNXMLUtil.XML_STYLE_SELF_CLOSING | SVNXMLUtil.XML_STYLE_PROTECT_CDATA, null, null); value = buf.toString(); } else { value = ""; } } else if (resource.getType() == DAVResourceType.HISTORY) { StringBuffer buf = SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.VERSION_HISTORY.getName(), SVNXMLUtil.XML_STYLE_SELF_CLOSING | SVNXMLUtil.XML_STYLE_PROTECT_CDATA, null, null); value = buf.toString(); } else if (resource.getType() == DAVResourceType.WORKSPACE) { StringBuffer buf = SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.COLLECTION.getName(), SVNXMLUtil.XML_STYLE_SELF_CLOSING | SVNXMLUtil.XML_STYLE_PROTECT_CDATA, null, null); value = buf.toString(); } else if (resource.getType() == DAVResourceType.ACTIVITY) { StringBuffer buf = SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.ACTIVITY.getName(), SVNXMLUtil.XML_STYLE_SELF_CLOSING | SVNXMLUtil.XML_STYLE_PROTECT_CDATA, null, null); value = buf.toString(); } else { return DAVInsertPropAction.NOT_DEF; } } else if (livePropElement == DAVElement.COMMENT || livePropElement == DAVElement.CREATOR_DISPLAY_NAME || livePropElement == DAVElement.DISPLAY_NAME || livePropElement == DAVElement.SOURCE) { return DAVInsertPropAction.NOT_DEF; } else { return DAVInsertPropAction.NOT_SUPP; } int ind = NAMESPACES.indexOf(livePropElement.getNamespace()); String prefix = "lp" + ind; if (propAction == DAVInsertPropAction.INSERT_NAME || (propAction == DAVInsertPropAction.INSERT_VALUE && (value == null || value.length() == 0))) { SVNXMLUtil.openXMLTag(prefix, livePropElement.getName(), SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, buffer); } else if (propAction == DAVInsertPropAction.INSERT_VALUE) { SVNXMLUtil.openCDataTag(prefix, livePropElement.getName(), value, null, false, false, buffer); } else { Map attrs = new HashMap(); attrs.put("D:name", livePropElement.getName()); attrs.put("D:namespace", livePropElement.getNamespace()); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.SUPPORTED_LIVE_PROPERTY.getName(), SVNXMLUtil.XML_STYLE_SELF_CLOSING, attrs, buffer); } return propAction; } private Date getLastModifiedTime2(DAVResource resource) throws SVNException { long revision = -1; if (resource.isBaseLined() && resource.getType() == DAVResourceType.VERSION) { revision = resource.getRevision(); } else if (resource.getType() == DAVResourceType.REGULAR || resource.getType() == DAVResourceType.WORKING || resource.getType() == DAVResourceType.VERSION) { revision = resource.getCreatedRevisionUsingFS(null); } else { SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_DAV_PROPS_NOT_FOUND, "Failed to determine property"), SVNLogType.NETWORK); } return resource.getRevisionDate(revision); } private void streamResponse(DAVResource resource, int status, DAVPropsResult propStats) { DAVResponse response = new DAVResponse(null, resource.getResourceURI().getRequestURI(), null, propStats, status); DAVXMLUtil.sendOneResponse(response, myResponseBuffer); } private void cacheBadProps() { if (myPropStat404 != null) { return; } myPropStat404 = new StringBuffer(); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROPSTAT.getName(), SVNXMLUtil.XML_STYLE_PROTECT_CDATA, null, myPropStat404); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROP.getName(), SVNXMLUtil.XML_STYLE_PROTECT_CDATA, null, myPropStat404); DAVElementProperty elem = myDocRoot.getChild(DAVElement.PROP); List childrenElements = elem.getChildren(); for (Iterator childrenIter = childrenElements.iterator(); childrenIter.hasNext();) { DAVElementProperty childElement = (DAVElementProperty) childrenIter.next(); DAVXMLUtil.addEmptyElement(DAVPropfindHandler.this.getNamespaces(), childElement.getName(), myPropStat404); } SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROP.getName(), myPropStat404); SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.STATUS.getName(), SVNXMLUtil.XML_STYLE_NORMAL, null, myPropStat404); myPropStat404.append("HTTP/1.1 404 Not Found"); SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.STATUS.getName(), myPropStat404); SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.PROPSTAT.getName(), myPropStat404); } private DAVPropfindRequest getPropfindRequest() { if (myDAVRequest == null) { myDAVRequest = new DAVPropfindRequest(); } return myDAVRequest; } private static class DAVInsertPropAction { public static final DAVInsertPropAction NOT_DEF = new DAVInsertPropAction(); public static final DAVInsertPropAction NOT_SUPP = new DAVInsertPropAction(); public static final DAVInsertPropAction INSERT_VALUE = new DAVInsertPropAction(); public static final DAVInsertPropAction INSERT_NAME = new DAVInsertPropAction(); public static final DAVInsertPropAction INSERT_SUPPORTED = new DAVInsertPropAction(); private DAVInsertPropAction() { } } }