/*
* ====================================================================
* 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 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.SVNPropertyValue;
import org.tmatesoft.svn.core.internal.io.dav.DAVElement;
import org.tmatesoft.svn.core.internal.util.SVNXMLUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.io.ISVNDeltaConsumer;
import org.tmatesoft.svn.core.io.ISVNFileRevisionHandler;
import org.tmatesoft.svn.core.io.SVNFileRevision;
import org.tmatesoft.svn.util.SVNLogType;
import org.xml.sax.Attributes;
/**
* @author TMate Software Ltd.
* @version 1.3
*/
public class DAVFileRevisionHandler extends BasicDAVDeltaHandler {
public static StringBuffer generateFileRevisionsRequest(StringBuffer xmlBuffer,
long startRevision,
long endRevision,
String path,
boolean includeMergedRevisions) {
xmlBuffer = xmlBuffer == null ? new StringBuffer() : xmlBuffer;
SVNXMLUtil.addXMLHeader(xmlBuffer);
SVNXMLUtil.openNamespaceDeclarationTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "file-revs-report", SVN_NAMESPACES_LIST, SVNXMLUtil.PREFIX_MAP, xmlBuffer);
if (startRevision >= 0) {
SVNXMLUtil.openCDataTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "start-revision", String.valueOf(startRevision), xmlBuffer);
}
if (endRevision >= 0) {
SVNXMLUtil.openCDataTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "end-revision", String.valueOf(endRevision), xmlBuffer);
}
if (includeMergedRevisions) {
SVNXMLUtil.openXMLTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "include-merged-revisions", SVNXMLUtil.XML_STYLE_SELF_CLOSING, null, xmlBuffer);
}
SVNXMLUtil.openCDataTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "path", path, xmlBuffer);
SVNXMLUtil.addXMLFooter(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "file-revs-report", xmlBuffer);
return xmlBuffer;
}
private static final DAVElement REVISION_PROPERTY = DAVElement.getElement(DAVElement.SVN_NAMESPACE, "rev-prop");
private static final DAVElement FILE_REVISION = DAVElement.getElement(DAVElement.SVN_NAMESPACE, "file-rev");
private static final DAVElement SET_PROPERTY = DAVElement.getElement(DAVElement.SVN_NAMESPACE, "set-prop");
private static final DAVElement DELETE_PROPERTY = DAVElement.getElement(DAVElement.SVN_NAMESPACE, "remove-prop");
private static final DAVElement MERGED_REVISION = DAVElement.getElement(DAVElement.SVN_NAMESPACE, "merged-revision");
private ISVNFileRevisionHandler myFileRevisionsHandler;
private String myPath;
private long myRevision;
private SVNProperties myProperties;
private SVNProperties myPropertiesDelta;
private String myPropertyName;
private String myPropertyEncoding;
private boolean myIsMergedRevision;
private int myCount;
public DAVFileRevisionHandler(ISVNFileRevisionHandler handler) {
myFileRevisionsHandler = handler;
myCount = 0;
init();
}
protected void startElement(DAVElement parent, DAVElement element, Attributes attrs) throws SVNException {
if (element == FILE_REVISION) {
myIsMergedRevision = false;
myPath = attrs.getValue("path");
if (myPath == null) {
missingAttributeError(element, "path");
}
String revString = attrs.getValue("rev");
if (revString == null) {
missingAttributeError(element, "rev");
}
try {
myRevision = Long.parseLong(revString);
} catch (NumberFormatException nfe) {
SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA, nfe), SVNLogType.NETWORK);
}
} else if (element == REVISION_PROPERTY || element == SET_PROPERTY || element == DELETE_PROPERTY) {
myPropertyName = attrs.getValue("name");
if (myPropertyName == null) {
missingAttributeError(element, "name");
}
myPropertyEncoding = attrs.getValue("encoding");
} else if (element == TX_DELTA) {
// handle file revision with props.
if (myPath != null && myFileRevisionsHandler != null) {
if (myProperties == null) {
myProperties = new SVNProperties();
}
if (myPropertiesDelta == null) {
myPropertiesDelta = new SVNProperties();
}
SVNFileRevision revision = new SVNFileRevision(myPath,
myRevision,
myProperties,
myPropertiesDelta,
myIsMergedRevision);
myFileRevisionsHandler.openRevision(revision);
myProperties = null;
myPropertiesDelta = null;
myPath = null;
myFileRevisionsHandler.applyTextDelta(myPath, null);
}
setDeltaProcessing(true);
} else if (element == MERGED_REVISION) {
myIsMergedRevision = true;
}
}
protected void endElement(DAVElement parent, DAVElement element, StringBuffer cdata) throws SVNException {
if (element == FILE_REVISION) {
if (myPath != null && myFileRevisionsHandler != null) {
// handle file revision if was not handled yet (no tx delta).
if (myProperties == null) {
myProperties = new SVNProperties();
}
if (myPropertiesDelta == null) {
myPropertiesDelta = new SVNProperties();
}
SVNFileRevision revision = new SVNFileRevision(myPath,
myRevision,
myProperties,
myPropertiesDelta);
myFileRevisionsHandler.openRevision(revision);
}
// handle close revision with props?
if (myFileRevisionsHandler != null) {
myFileRevisionsHandler.closeRevision(myPath);
}
myPath = null;
myProperties = null;
myPropertiesDelta = null;
myPropertyEncoding = null;
myPropertyName = null;
} else if (element == TX_DELTA) {
setDeltaProcessing(false);
myCount++;
} else if (element == REVISION_PROPERTY) {
if (myProperties == null) {
myProperties = new SVNProperties();
}
myProperties.put(myPropertyName, cdata != null ? cdata.toString() : "");
myPropertyName = null;
} else if (element == SET_PROPERTY) {
if (myPropertiesDelta == null) {
myPropertiesDelta = new SVNProperties();
}
if (myPropertyName != null) {
SVNPropertyValue propertyValue = createPropertyValue(null, myPropertyName, cdata, myPropertyEncoding);
myPropertiesDelta.put(myPropertyName, propertyValue);
}
myPropertyName = null;
myPropertyEncoding = null;
} else if (element == DELETE_PROPERTY) {
if (myPropertiesDelta == null) {
myPropertiesDelta = new SVNProperties();
}
if (myPropertyName != null) {
myPropertiesDelta.put(myPropertyName, (byte[]) null);
}
myPropertyEncoding = null;
myPropertyName = null;
}
}
public int getEntriesCount() {
return myCount;
}
protected ISVNDeltaConsumer getDeltaConsumer() {
return myFileRevisionsHandler;
}
protected String getCurrentPath() {
return myPath;
}
private void missingAttributeError(DAVElement element, String attr) throws SVNException {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA,
"Missing attribute ''{0}'' on element {1}",
new Object[]{attr, element});
SVNErrorManager.error(err, SVNLogType.NETWORK);
}
}