/*
* ====================================================================
* Copyright (c) 2004-2012 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.io.dav.handlers;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import org.tmatesoft.svn.core.SVNCommitInfo;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
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.dav.DAVUtil;
import org.tmatesoft.svn.core.internal.util.SVNDate;
import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.util.SVNXMLUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.io.ISVNWorkspaceMediator;
import org.tmatesoft.svn.util.SVNLogType;
import org.xml.sax.Attributes;
/**
* @author TMate Software Ltd.
* @version 1.3
*/
public class DAVMergeHandler extends BasicDAVHandler {
public static StringBuffer generateMergeRequest(StringBuffer xmlBuffer, String path, String activityURL,
Map locks) {
xmlBuffer = xmlBuffer == null ? new StringBuffer() : xmlBuffer;
SVNXMLUtil.addXMLHeader(xmlBuffer);
SVNXMLUtil.openNamespaceDeclarationTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "merge", DAV_NAMESPACES_LIST,
SVNXMLUtil.PREFIX_MAP, xmlBuffer);
SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "source", SVNXMLUtil.XML_STYLE_NORMAL, null,
xmlBuffer);
SVNXMLUtil.openCDataTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "href", activityURL, xmlBuffer);
SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "source", xmlBuffer);
SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "no-auto-merge",
SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, xmlBuffer);
SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "no-checkout",
SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, xmlBuffer);
SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "prop", SVNXMLUtil.XML_STYLE_NORMAL, null,
xmlBuffer);
SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "checked-in",
SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, xmlBuffer);
SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "version-name",
SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, xmlBuffer);
SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "resourcetype",
SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, xmlBuffer);
SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "creationdate",
SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, xmlBuffer);
SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "creator-displayname",
SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, xmlBuffer);
SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "prop", xmlBuffer);
if (locks != null && !locks.isEmpty()) {
xmlBuffer = generateLockDataRequest(xmlBuffer, path, null, locks);
}
SVNXMLUtil.addXMLFooter(SVNXMLUtil.DAV_NAMESPACE_PREFIX, "merge", xmlBuffer);
return xmlBuffer;
}
public static StringBuffer generateLockDataRequest(StringBuffer target, String root, String path, Map locks) {
target = target == null ? new StringBuffer() : target;
SVNXMLUtil.openNamespaceDeclarationTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "lock-token-list",
SVN_NAMESPACES_LIST, SVNXMLUtil.PREFIX_MAP, target);
for (Iterator paths = locks.keySet().iterator(); paths.hasNext();) {
String lockPath = (String) paths.next();
if (path == null || SVNPathUtil.getPathAsChild(path, lockPath) != null) {
String relativePath = SVNPathUtil.getRelativePath(root, lockPath);
String token = (String) locks.get(lockPath);
SVNXMLUtil.openXMLTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "lock", SVNXMLUtil.XML_STYLE_NORMAL,
null, target);
SVNXMLUtil.openCDataTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "lock-path",
SVNEncodingUtil.uriDecode(relativePath), target);
SVNXMLUtil.openCDataTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "lock-token", token, target);
SVNXMLUtil.closeXMLTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "lock", target);
}
}
SVNXMLUtil.closeXMLTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "lock-token-list", target);
return target;
}
public static boolean hasChildPaths(String path, Map locks) {
for (Iterator paths = locks.keySet().iterator(); paths.hasNext();) {
String lockPath = (String) paths.next();
if (SVNPathUtil.getPathAsChild(path, lockPath) != null) {
return true;
}
}
return false;
}
private ISVNWorkspaceMediator myMediator;
private Map myPathsMap;
private static final DAVElement RESPONSE = DAVElement.getElement(DAVElement.DAV_NAMESPACE, "response");
private static final DAVElement POST_COMMIT_ERROR = DAVElement.getElement(DAVElement.SVN_NAMESPACE, "post-commit-err");
private String myAuthor;
private Date myCommitDate;
private long myRevision;
private String myRepositoryPath;
private String myVersionPath;
private DAVElement myResourceType;
private SVNCommitInfo myCommitInfo;
private SVNErrorMessage myPostCommitError;
public DAVMergeHandler(ISVNWorkspaceMediator mediator, Map pathsMap) {
myMediator = mediator;
myPathsMap = pathsMap;
init();
}
public SVNCommitInfo getCommitInfo() {
return myCommitInfo;
}
protected void startElement(DAVElement parent, DAVElement element, Attributes attrs) throws SVNException {
if (element == RESPONSE) {
myResourceType = null;
myRepositoryPath = null;
myVersionPath = null;
myAuthor = null;
myCommitDate = null;
myRevision = -1;
}
}
protected void endElement(DAVElement parent, DAVElement element, StringBuffer cdata) throws SVNException {
if (element == POST_COMMIT_ERROR) {
myPostCommitError = SVNErrorMessage.create(SVNErrorCode.REPOS_POST_COMMIT_HOOK_FAILED, cdata.toString(), SVNErrorMessage.TYPE_WARNING);
} else if (element == DAVElement.HREF) {
if (parent == RESPONSE) {
myRepositoryPath = cdata.toString();
myRepositoryPath = SVNEncodingUtil.uriDecode(myRepositoryPath);
myRepositoryPath = SVNPathUtil.canonicalizePath(myRepositoryPath);
} else if (parent == DAVElement.CHECKED_IN) {
myVersionPath = cdata.toString();
myVersionPath = SVNPathUtil.canonicalizePath(myVersionPath);
}
} else if (parent == DAVElement.RESOURCE_TYPE && element == DAVElement.BASELINE) {
myResourceType = element;
} else if (parent == DAVElement.RESOURCE_TYPE && element == DAVElement.COLLECTION) {
myResourceType = element;
} else if (element == RESPONSE) {
// all resource info is collected, do something.
if (myResourceType == DAVElement.BASELINE) {
myCommitInfo = new SVNCommitInfo(myRevision, myAuthor, myCommitDate, myPostCommitError);
} else {
String reposPath = SVNEncodingUtil.uriEncode(myRepositoryPath);
String path = (String) myPathsMap.get(reposPath);
if (path != null && myMediator != null) {
String versionURLPropName = SVNProperty.WC_URL; //"svn:wc:ra_dav:version-url";
SVNPropertyValue urlPropertyValue = DAVUtil.isUseDAVWCURL() ? SVNPropertyValue.create(myVersionPath) : null;
myMediator.setWorkspaceProperty(SVNEncodingUtil.uriDecode(path), versionURLPropName, urlPropertyValue);
}
}
} else if (element == DAVElement.CREATION_DATE) {
myCommitDate = SVNDate.parseDate(cdata.toString());
} else if (element == DAVElement.CREATOR_DISPLAY_NAME) {
myAuthor = cdata.toString();
} else if (element == DAVElement.VERSION_NAME) {
try {
myRevision = Long.parseLong(cdata.toString());
} catch (NumberFormatException nfe) {
SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA, nfe), SVNLogType.NETWORK);
}
} else if (parent == DAVElement.PROPSTAT && element == DAVElement.STATUS) {
// should be 200
}
}
}