/*
* ====================================================================
* 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() {
}
}
}