/*
* ====================================================================
* 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.Date;
import java.util.Enumeration;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.tmatesoft.svn.core.SVNDirEntry;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
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.DAVResourceType;
import org.tmatesoft.svn.core.internal.util.SVNDate;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.util.SVNLogType;
import org.tmatesoft.svn.util.Version;
/**
* @author TMate Software Ltd.
* @version 1.2.0
*/
public class DAVGetHandler extends ServletDAVHandler {
public DAVGetHandler(DAVRepositoryManager connector, HttpServletRequest request, HttpServletResponse response) {
super(connector, request, response);
}
public void execute() throws SVNException {
DAVResource resource = getRequestedDAVResource(true, false);
if (!resource.exists()) {
SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_DAV_PATH_NOT_FOUND, "Path ''{0}'' you requested not found", resource.getResourceURI().getPath()), SVNLogType.NETWORK);
}
if (resource.getResourceURI().getType() != DAVResourceType.REGULAR && resource.getResourceURI().getType() != DAVResourceType.VERSION
&& resource.getResourceURI().getType() != DAVResourceType.WORKING) {
SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA, "Cannot GET this type of resource."), SVNLogType.NETWORK);
}
setDefaultResponseHeaders();
setResponseHeaders(resource);
try {
checkPreconditions(resource.getETag(), resource.getLastModified());
} catch (SVNException e) {
//Nothing to do, there are no enough conditions
}
if (resource.isCollection()) {
StringBuffer body = new StringBuffer();
generateResponseBody(resource, body);
String responseBody = body.toString();
try {
setResponseContentLength(responseBody.getBytes(UTF8_ENCODING).length);
} catch (UnsupportedEncodingException e) {
setResponseContentLength(responseBody.getBytes().length);
}
try {
getResponseWriter().write(responseBody);
} catch (IOException e) {
SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED, e), e, SVNLogType.NETWORK);
}
} else if (resource.getDeltaBase() != null) {
//Here we should send SVN delta (for old clients)
} else {
resource.writeTo(getResponseOutputStream());
}
}
protected DAVRequest getDAVRequest() {
return null;
}
protected int checkPreconditions(String eTag, Date lastModified) {
super.checkPreconditions(eTag, lastModified);
lastModified = lastModified == null ? new Date() : lastModified;
boolean isNotModified = false;
Enumeration ifNoneMatch = getRequestHeaders(IF_NONE_MATCH_HEADER);
if (ifNoneMatch != null && ifNoneMatch.hasMoreElements()) {
if (eTag != null) {
if (getRequestHeaders(RANGE_HEADER) != null && getRequestHeaders(RANGE_HEADER).hasMoreElements()) {
isNotModified = !eTag.startsWith("W") && containsValue(ifNoneMatch, eTag, "*");
} else {
isNotModified = containsValue(ifNoneMatch, eTag, "*");
}
}
}
long ifModified = getRequestDateHeader(IF_MODIFIED_SINCE_HEADER);
long date = getRequestDateHeader(DATE_HEADER);
if ((isNotModified || ifNoneMatch == null || !ifNoneMatch.hasMoreElements()) && ifModified != -1 && date != -1) {
isNotModified = ifModified >= lastModified.getTime() && ifModified <= date;
}
if (isNotModified) {
// TODO status HTTP_NOT_MODIFIED
} else {
//TODO status OK
}
return 0;//TODO
}
private void setResponseHeaders(DAVResource resource) {
try {
setResponseContentType(resource.getContentType());
} catch (SVNException e) {
//nothing to do we just skip this header
}
setResponseHeader(ACCEPT_RANGES_HEADER, ACCEPT_RANGES_DEFAULT_VALUE);
try {
Date lastModifiedTime = resource.getLastModified();
if (lastModifiedTime != null) {
setResponseHeader(LAST_MODIFIED_HEADER, SVNDate.formatRFC1123Date(lastModifiedTime));
}
} catch (SVNException e) {
//nothing to do we just skip this header
}
String eTag = resource.getETag();
if (eTag != null) {
setResponseHeader(ETAG_HEADER, eTag);
}
}
private void generateResponseBody(DAVResource resource, StringBuffer buffer) throws SVNException {
startBody(SVNPathUtil.tail(resource.getResourceURI().getContext()), resource.getResourceURI().getPath(), resource.getRevision(), buffer);
addUpperDirectoryLink(resource.getResourceURI().getContext(), resource.getResourceURI().getPath(), buffer);
addDirectoryEntries(resource, buffer);
finishBody(buffer);
}
private void startBody(String contextComponent, String path, long revision, StringBuffer buffer) {
buffer.append("<html><head><title>");
buffer.append(contextComponent);
buffer.append(" - Revision ");
buffer.append(String.valueOf(revision));
buffer.append(": ");
buffer.append(path);
buffer.append("</title></head>\n");
buffer.append("<body>\n<h2>");
buffer.append(contextComponent);
buffer.append(" - Revision ");
buffer.append(String.valueOf(revision));
buffer.append(": ");
buffer.append(path);
buffer.append("</h2>\n <ul>\n");
}
private void addUpperDirectoryLink(String context, String path, StringBuffer buffer) {
if (!"/".equals(path)) {
buffer.append("<li><a href=\"");
buffer.append(context);
String parent = DAVPathUtil.removeTail(path, true);
buffer.append("/".equals(parent) ? "" : parent);
buffer.append("/");
buffer.append("\">..</a></li>\n");
}
}
private void addDirectoryEntries(DAVResource resource, StringBuffer buffer) throws SVNException {
for (Iterator iterator = resource.getEntries().iterator(); iterator.hasNext();) {
SVNDirEntry entry = (SVNDirEntry) iterator.next();
boolean isDir = entry.getKind() == SVNNodeKind.DIR;
buffer.append("<li><a href=\"");
buffer.append(resource.getResourceURI().getContext());
buffer.append("/".equals(resource.getResourceURI().getPath()) ? "" : resource.getResourceURI().getPath());
buffer.append(DAVPathUtil.standardize(entry.getName()));
buffer.append(isDir ? "/" : "");
buffer.append("\">");
buffer.append(entry.getName());
buffer.append(isDir ? "/" : "");
buffer.append("</a></li>\n");
}
}
private void finishBody(StringBuffer buffer) {
buffer.append("</ul><hr noshade><em>");
buffer.append("Powered by ");
buffer.append(Version.getVersionString());
buffer.append("</em>\n</body></html>");
}
}