/*
* ====================================================================
* 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.server.dav.handlers;
import java.util.HashMap;
import java.util.Iterator;
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.internal.io.dav.DAVElement;
import org.tmatesoft.svn.core.internal.io.fs.FSLocationsFinder;
import org.tmatesoft.svn.core.internal.server.dav.DAVException;
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.DAVXMLUtil;
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.ISVNLocationSegmentHandler;
import org.tmatesoft.svn.core.io.SVNLocationSegment;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.util.SVNLogType;
/**
* @version 1.3
* @author TMate Software Ltd.
*/
public class DAVGetLocationSegmentsHandler extends DAVReportHandler implements ISVNLocationSegmentHandler {
private static final String GET_LOCATION_SEGMENTS_REPORT = "get-location-segments-report";
private static final String LOCATION_SEGMENT_TAG = "location-segment";
private static final String RANGE_START_ATTR = "range-start";
private static final String RANGE_END_ATTR = "range-end";
private DAVGetLocationSegmentsRequest myDAVRequest;
private boolean myIsOpenerSent;
private DAVReportHandler myCommonReportHandler;
protected DAVGetLocationSegmentsHandler(DAVRepositoryManager repositoryManager, HttpServletRequest request, HttpServletResponse response,
DAVReportHandler commonReportHandler) {
super(repositoryManager, request, response);
myCommonReportHandler = commonReportHandler;
}
public void execute() throws SVNException {
myCommonReportHandler.checkSVNNamespace(null);
DAVResource resource = getRequestedDAVResource(false, false);
setDAVResource(resource);
DAVGetLocationSegmentsRequest request = getLocationSegmentsRequest();
String path = null;
long startRev = -1;
long endRev = -1;
long pegRev = -1;
DAVElementProperty rootElement = request.getRootElement();
List children = rootElement.getChildren();
for (Iterator iterator = children.iterator(); iterator.hasNext();) {
DAVElementProperty childElement = (DAVElementProperty) iterator.next();
DAVElement childElementName = childElement.getName();
if (!DAVElement.SVN_NAMESPACE.equals(childElementName.getNamespace())) {
continue;
}
if (childElementName == DAVElement.PATH) {
path = childElement.getFirstValue(false);
DAVPathUtil.testCanonical(path);
String resourcePath = resource.getResourceURI().getPath();
path = SVNPathUtil.append(resourcePath, path);
} else if (childElementName == DAVElement.START_REVISION) {
try {
startRev = Long.parseLong(childElement.getFirstValue(true));
} catch (NumberFormatException nfe) {
SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED, nfe), SVNLogType.NETWORK);
}
} else if (childElementName == DAVElement.END_REVISION) {
try {
endRev = Long.parseLong(childElement.getFirstValue(true));
} catch (NumberFormatException nfe) {
SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED, nfe), SVNLogType.NETWORK);
}
} else if (childElementName == DAVElement.PEG_REVISION) {
try {
pegRev = Long.parseLong(childElement.getFirstValue(true));
} catch (NumberFormatException nfe) {
SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED, nfe), SVNLogType.NETWORK);
}
}
}
if (path == null) {
throw new DAVException("Not all parameters passed.", HttpServletResponse.SC_BAD_REQUEST, SVNLogType.NETWORK, DAVXMLUtil.SVN_DAV_ERROR_TAG,
DAVElement.SVN_DAV_ERROR_NAMESPACE);
}
if (SVNRevision.isValidRevisionNumber(startRev) && SVNRevision.isValidRevisionNumber(endRev) &&
endRev > startRev) {
throw new DAVException("End revision must not be younger than start revision", HttpServletResponse.SC_BAD_REQUEST, SVNLogType.NETWORK,
DAVXMLUtil.SVN_DAV_ERROR_TAG, DAVElement.SVN_DAV_ERROR_NAMESPACE);
}
if (SVNRevision.isValidRevisionNumber(pegRev) && SVNRevision.isValidRevisionNumber(startRev) &&
startRev > pegRev) {
throw new DAVException("Start revision must not be younger than peg revision", HttpServletResponse.SC_BAD_REQUEST, SVNLogType.NETWORK,
DAVXMLUtil.SVN_DAV_ERROR_TAG, DAVElement.SVN_DAV_ERROR_NAMESPACE);
}
FSLocationsFinder locationsFinder = new FSLocationsFinder(getDAVResource().getFSFS());
locationsFinder.getNodeLocationSegments(path, pegRev, startRev, endRev, this);
try {
maybeSendOpener();
} catch (SVNException svne) {
throw DAVException.convertError(svne.getErrorMessage(), HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Error beginning REPORT reponse", null);
}
try {
writeXMLFooter(GET_LOCATION_SEGMENTS_REPORT);
} catch (SVNException svne) {
throw DAVException.convertError(svne.getErrorMessage(), HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Error ending REPORT reponse", null);
}
}
public void handleLocationSegment(SVNLocationSegment locationSegment) throws SVNException {
maybeSendOpener();
Map attrs = new HashMap();
String path = locationSegment.getPath();
if (path != null) {
String quotedPath = SVNEncodingUtil.xmlEncodeCDATA(path, true);
attrs.put(PATH_ATTR, quotedPath);
attrs.put(RANGE_START_ATTR, String.valueOf(locationSegment.getStartRevision()));
attrs.put(RANGE_END_ATTR, String.valueOf(locationSegment.getEndRevision()));
} else {
attrs.put(RANGE_START_ATTR, String.valueOf(locationSegment.getStartRevision()));
attrs.put(RANGE_END_ATTR, String.valueOf(locationSegment.getEndRevision()));
}
StringBuffer buffer = SVNXMLUtil.openXMLTag(SVNXMLUtil.SVN_NAMESPACE_PREFIX, LOCATION_SEGMENT_TAG, SVNXMLUtil.XML_STYLE_SELF_CLOSING, attrs, null);
write(buffer);
}
protected DAVRequest getDAVRequest() {
return getLocationSegmentsRequest();
}
private DAVGetLocationSegmentsRequest getLocationSegmentsRequest() {
if (myDAVRequest == null) {
myDAVRequest = new DAVGetLocationSegmentsRequest();
}
return myDAVRequest;
}
private void maybeSendOpener() throws SVNException {
if (!myIsOpenerSent) {
writeXMLHeader(GET_LOCATION_SEGMENTS_REPORT);
myIsOpenerSent = true;
}
}
}