pnever 2004/04/25 10:33:50
Modified: src/webdav/server/org/apache/slide/webdav/method
PutMethod.java GetMethod.java
AbstractWebdavMethod.java
Log:
FIXED BUG: If headers were not checked for PUT
Revision Changes Path
1.73 +25 -4
jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PutMethod.java
Index: PutMethod.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PutMethod.java,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- PutMethod.java 24 Feb 2004 17:03:34 -0000 1.72
+++ PutMethod.java 25 Apr 2004 17:33:50 -0000 1.73
@@ -5,7 +5,7 @@
*
* ====================================================================
*
- * Copyright 1999-2002 The Apache Software Foundation
+ * Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -192,6 +192,16 @@
revisionDescriptor.setContentLength(-1);
}
+ ResourceInfo resourceInfo =
+ new ResourceInfo(resourcePath, revisionDescriptor);
+
+ // Checking If headers
+ if (!checkIfHeaders(req, resp, resourceInfo)) {
+ int statusCode = WebdavStatus.SC_PRECONDITION_FAILED;
+ sendError( statusCode, "Check If Header failed" );
+ throw new WebdavException( statusCode );
+ }
+
ResourceKind resourceKind =
AbstractResourceKind.determineResourceKind(token, resourcePath, revisionDescriptor);
versioningHelper.isWriteLocked(slideToken, revisionDescriptors);
@@ -299,6 +309,17 @@
NodeRevisionDescriptor revisionDescriptor =
new NodeRevisionDescriptor(req.getContentLength());
+
+ ResourceInfo resourceInfo =
+ new ResourceInfo(resourcePath, revisionDescriptor);
+ resourceInfo.exists = false;
+
+ // Checking If headers
+ if (!checkIfHeaders(req, resp, resourceInfo)) {
+ int statusCode = WebdavStatus.SC_PRECONDITION_FAILED;
+ sendError( statusCode, "Check If Header failed" );
+ throw new WebdavException( statusCode );
+ }
//NodeProperty property = null;
1.44 +4 -248
jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/GetMethod.java
Index: GetMethod.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/GetMethod.java,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -r1.43 -r1.44
--- GetMethod.java 24 Feb 2004 17:03:33 -0000 1.43
+++ GetMethod.java 25 Apr 2004 17:33:50 -0000 1.44
@@ -5,7 +5,7 @@
*
* ====================================================================
*
- * Copyright 1999-2002 The Apache Software Foundation
+ * Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,10 +27,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
-import java.util.Locale;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.servlet.ServletOutputStream;
@@ -73,15 +71,6 @@
protected final int BUFFER_SIZE = 2048;
- /**
- * The set of SimpleDateFormat formats to use in getDateHeader().
- */
- protected static final SimpleDateFormat formats[] = {
- new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
- new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
- new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
- };
-
/**
* MIME multipart separation string
@@ -343,186 +332,6 @@
// -------------------------------------------------------- Private Methods
- /**
- * Check if the conditions specified in the optional If headers are
- * satisfied.
- *
- * @param request The servlet request we are processing
- * @param response The servlet response we are creating
- * @param resourceInfo File object
- * @return boolean true if the resource meets all the specified conditions,
- * and false if any of the conditions is not satisfied, in which case
- * request processing is stopped
- */
- private boolean checkIfHeaders(HttpServletRequest request,
- HttpServletResponse response,
- ResourceInfo resourceInfo)
- throws IOException {
-
- String eTag = getETag(resourceInfo, true);
- long fileLength = resourceInfo.length;
- long lastModified = resourceInfo.date;
-
- StringTokenizer commaTokenizer;
-
- String headerValue;
-
- // Checking If-Match
- headerValue = request.getHeader("If-Match");
- if (headerValue != null) {
- if (headerValue.indexOf("*") == -1) {
-
- commaTokenizer = new StringTokenizer(headerValue, ",");
- boolean conditionSatisfied = false;
-
- while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
- String currentToken = commaTokenizer.nextToken();
- if (currentToken.trim().equals(eTag))
- conditionSatisfied = true;
- }
-
- // If none of the given ETags match, 412 Precodition failed is
- // sent back
- if (!conditionSatisfied) {
- response.sendError
- (HttpServletResponse.SC_PRECONDITION_FAILED);
- return false;
- }
-
- }
- }
-
- // Checking If-Modified-Since
- headerValue = request.getHeader("If-Modified-Since");
- if (headerValue != null) {
-
- // If an If-None-Match header has been specified, if modified since
- // is ignored.
- if (request.getHeader("If-None-Match") == null) {
-
- Date date = null;
-
- // Parsing the HTTP Date
- for (int i = 0; (date == null) && (i < formats.length); i++) {
- try {
- synchronized (formats[i]) {
- date = formats[i].parse(headerValue);
- }
- } catch (ParseException e) {
- ;
- }
- }
-
- if ((date != null)
- && (lastModified <= (date.getTime() + 1000)) ) {
- // The entity has not been modified since the date
- // specified by the client. This is not an error case.
- response.sendError
- (HttpServletResponse.SC_NOT_MODIFIED);
- return false;
- }
-
- }
-
- }
-
- // Checking If-None-Match
- headerValue = request.getHeader("If-None-Match");
- if (headerValue != null) {
- if (headerValue.indexOf("*") == -1) {
-
- commaTokenizer = new StringTokenizer(headerValue, ",");
- boolean conditionSatisfied = false;
-
- while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
- String currentToken = commaTokenizer.nextToken();
- if (currentToken.trim().equals(eTag))
- conditionSatisfied = true;
- }
-
- if (conditionSatisfied) {
-
- // For GET and HEAD, we should respond with
- // 304 Not Modified.
- // For every other method, 412 Precondition Failed is sent
- // back.
- if ( ("GET".equals(request.getMethod()))
- || ("HEAD".equals(request.getMethod())) ) {
- response.sendError
- (HttpServletResponse.SC_NOT_MODIFIED);
- return false;
- } else {
- response.sendError
- (HttpServletResponse.SC_PRECONDITION_FAILED);
- return false;
- }
- }
-
- } else {
- if (resourceInfo.exists()) {
-
- }
- }
- }
-
- // Checking If-Unmodified-Since
- headerValue = request.getHeader("If-Unmodified-Since");
- if (headerValue != null) {
-
- Date date = null;
-
- // Parsing the HTTP Date
- for (int i = 0; (date == null) && (i < formats.length); i++) {
- try {
- synchronized (formats[i]) {
- date = formats[i].parse(headerValue);
- }
- } catch (ParseException e) {
- ;
- }
- }
-
- if ( (date != null) && (lastModified > date.getTime()) ) {
- // The entity has not been modified since the date
- // specified by the client. This is not an error case.
- response.sendError
- (HttpServletResponse.SC_PRECONDITION_FAILED);
- return false;
- }
-
- }
-
- return true;
- }
-
-
- /**
- * Get the ETag value associated with a file.
- *
- * @param resourceInfo File object
- * @param strong True if we want a strong ETag, in which case a checksum
- * of the file has to be calculated
- */
- private String getETagValue(ResourceInfo resourceInfo, boolean strong) {
- // FIXME : Compute a strong ETag if requested, using an MD5 digest
- // of the file contents
- return resourceInfo.length + "-" + resourceInfo.date;
- }
-
-
- /**
- * Get the ETag associated with a file.
- *
- * @param resourceInfo File object
- * @param strong True if we want a strong ETag, in which case a checksum
- * of the file has to be calculated
- */
- private String getETag(ResourceInfo resourceInfo, boolean strong) {
- if (strong)
- return "\"" + getETagValue(resourceInfo, strong) + "\"";
- else
- return "W/\"" + getETagValue(resourceInfo, strong) + "\"";
- }
/**
@@ -927,57 +736,4 @@
}
}
-
-
- // ---------------------------------------------- ResourceInfo Inner Class
-
-
- private class ResourceInfo {
-
-
- /**
- * Constructor.
- *
- * @param pathname Path name of the file
- */
- public ResourceInfo(String path, NodeRevisionDescriptor properties) {
-
- this.path = path;
- this.exists = true;
- this.creationDate = properties.getCreationDateAsDate().getTime();
- this.date = properties.getLastModifiedAsDate().getTime();
- this.httpDate = properties.getLastModified();
- this.length = properties.getContentLength();
-
- }
-
-
- public String path;
- public long creationDate;
- public String httpDate;
- public long date;
- public long length;
- //public boolean collection;
- public boolean exists;
-
-
- /**
- * Test if the associated resource exists.
- */
- public boolean exists() {
- return exists;
- }
-
-
- /**
- * String representation.
- */
- public String toString() {
- return path;
- }
-
-
- }
-
-
}
1.27 +368 -112
jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/AbstractWebdavMethod.java
Index: AbstractWebdavMethod.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/AbstractWebdavMethod.java,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- AbstractWebdavMethod.java 2 Apr 2004 07:30:28 -0000 1.26
+++ AbstractWebdavMethod.java 25 Apr 2004 17:33:50 -0000 1.27
@@ -5,7 +5,7 @@
*
* ====================================================================
*
- * Copyright 1999-2002 The Apache Software Foundation
+ * Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,11 +27,18 @@
import java.io.StringWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.util.*;
-
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
import org.apache.slide.common.Domain;
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.NestedSlideException;
@@ -41,10 +48,10 @@
import org.apache.slide.common.SlideTokenWrapper;
import org.apache.slide.content.Content;
import org.apache.slide.content.NodeProperty;
+import org.apache.slide.content.NodeProperty.NamespaceCache;
import org.apache.slide.content.NodeRevisionContent;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
-import org.apache.slide.content.NodeProperty.NamespaceCache;
import org.apache.slide.lock.Lock;
import org.apache.slide.lock.NodeLock;
import org.apache.slide.lock.UnlockListener;
@@ -60,7 +67,15 @@
import org.apache.slide.webdav.WebdavException;
import org.apache.slide.webdav.WebdavMethod;
import org.apache.slide.webdav.WebdavServletConfig;
-import org.apache.slide.webdav.util.*;
+import org.apache.slide.webdav.util.BindConstants;
+import org.apache.slide.webdav.util.DeltavConstants;
+import org.apache.slide.webdav.util.NotificationConstants;
+import org.apache.slide.webdav.util.PreconditionViolationException;
+import org.apache.slide.webdav.util.TransactionConstants;
+import org.apache.slide.webdav.util.UnlockListenerImpl;
+import org.apache.slide.webdav.util.ViolatedPrecondition;
+import org.apache.slide.webdav.util.WebdavConstants;
+import org.apache.slide.webdav.util.WebdavUtils;
import org.apache.util.MD5Encoder;
import org.apache.util.WebdavStatus;
import org.jdom.Document;
@@ -122,6 +137,14 @@
protected static final Namespace DNSP = NamespaceCache.DEFAULT_NAMESPACE;
+ /**
+ * The set of SimpleDateFormat formats to use in getDateHeader().
+ */
+ protected static final SimpleDateFormat formats[] = {
+ new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
+ new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
+ new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
+ };
// ----------------------------------------------------- Instance Variables
@@ -243,11 +266,11 @@
throw new IllegalStateException();
}
}
-
-
+
+
// ----------------------------------------------------------- Constructors
-
-
+
+
/**
* Constructor.
*
@@ -256,10 +279,10 @@
*/
public AbstractWebdavMethod(NamespaceAccessToken token,
WebdavServletConfig config) {
-
+
this.config = config;
this.token = token;
-
+
// initialize helpers
structure = token.getStructureHelper();
content = token.getContentHelper();
@@ -267,11 +290,11 @@
lock = token.getLockHelper();
macro = token.getMacroHelper();
}
-
-
+
+
// -------------------------------------------- WebdavMethod Implementation
-
-
+
+
/**
* Exceute method.
*
@@ -279,13 +302,13 @@
*/
public void run(HttpServletRequest req, HttpServletResponse resp)
throws WebdavException {
-
+
this.req = req;
this.resp = resp;
this.slideToken = WebdavUtils.getSlideToken(req);
this.requestUri = WebdavUtils.getRelativePath(req, config);
parseRequestHeaders();
-
+
boolean transactionIsStarted = false;
try {
parseRequest();
@@ -293,19 +316,19 @@
token.begin();
transactionIsStarted = true;
}
-
+
// clear expired lock-tokens
try {
UnlockListener listener =
new UnlockListenerImpl( slideToken, token, config, req, resp );
lock.clearExpiredLocks( slideToken, requestUri, listener );
-
+
// if the URI has no more locks associated to it and is
// a lock-null resource, we must attempt to delete it
-
+
Enumeration locks = lock.enumerateLocks(slideToken, requestUri);
if (!locks.hasMoreElements()) {
-
+
NodeRevisionDescriptors revisionDescriptors =
content.retrieve(slideToken, requestUri);
NodeRevisionDescriptor revisionDescriptor =
content.retrieve(slideToken, revisionDescriptors);
if (isLockNull(revisionDescriptor)) {
@@ -318,7 +341,7 @@
}
catch (SlideException e) {}
-
+
executeRequest();
if (methodNeedsTransactionSupport()) {
token.commit();
@@ -375,11 +398,11 @@
public String getSlidePath(String fullpath) {
return WebdavUtils.getSlidePath(fullpath, req.getContextPath());
}
-
-
+
+
// ------------------------------------------------------ Protected Methods
-
-
+
+
/**
* Return true if the method needs transaction support.
* Return true if the method needs transaction support, e.g.
@@ -392,8 +415,8 @@
// overwrite it to true, but PropFind creates a RevisionDescriptors
// on the fly
}
-
-
+
+
/**
* Read request contents.
*
@@ -401,12 +424,12 @@
* @return char[] Array of char which contains the body of the request
*/
protected void readRequestContent() {
-
+
if (req.getContentLength() == 0)
return;
-
+
// TODO : Modify this and make it chunking aware
-
+
try {
requestBody = new String(NodeRevisionContent.read(req.getInputStream()),
getEncodingString(req.getCharacterEncoding()));
@@ -415,9 +438,9 @@
token.getLogger().log(e,LOG_CHANNEL,Logger.ERROR);
}
}
-
-
-
+
+
+
/**
* Translate the encoding string into a proper Java encoding String.
*/
@@ -428,8 +451,8 @@
if (result.endsWith("\"")) result = result.substring(0,
result.length()-1);
return result;
}
-
-
+
+
/**
* Method parseHeaders
*
@@ -437,14 +460,14 @@
private void parseRequestHeaders() throws WebdavException {
requestHeaders.parse();
}
-
+
/**
* Test if a resource given by a path is a collection
*/
protected boolean isCollection(String path) {
return WebdavUtils.isCollection(token, slideToken, path);
}
-
+
/**
* Test whether the resource given by lowerNode is a descendant of the
* resource given by upperNode
@@ -463,7 +486,7 @@
if (upperNode.hasBinding(lowerNode)) {
return true;
}
-
+
// use a non-blocking slide token.
SlideToken stoken = readonlySlideToken();
@@ -472,7 +495,7 @@
try {
lowerNrds = content.retrieve(stoken, lowerNode.getUri());
lowerNrd = content.retrieve(stoken, lowerNrds);
-
+
NodeProperty psProp = lowerNrd.getProperty(P_PARENT_SET);
XMLValue xv = new XMLValue( String.valueOf(psProp.getValue()) );
Iterator i = xv.getList().iterator();
@@ -486,11 +509,11 @@
} catch (ServiceAccessException e) {
throw e;
} catch (Exception e) {}
-
+
return false;
}
-
-
+
+
/**
* Parse WebDAV XML query.
*
@@ -498,9 +521,9 @@
*/
protected abstract void parseRequest()
throws WebdavException;
-
-
-
+
+
+
/**
* Returns the request content (XML) Document.
*
@@ -509,9 +532,9 @@
protected Document getRequestContent() {
return requestContentDocument;
}
-
+
//--
-
+
/**
* precondition: sourceUri != null
*/
@@ -532,12 +555,12 @@
if ((hostName != null) && (uri.startsWith(hostName))) {
uri = uri.substring(hostName.length());
}
-
+
int portIndex = uri.indexOf(":");
if (portIndex >= 0) {
uri = uri.substring(portIndex);
}
-
+
if (uri.startsWith(":")) {
int firstSeparator = uri.indexOf("/");
if (firstSeparator < 0) {
@@ -547,16 +570,16 @@
}
}
}
-
+
// headers are "ISO-8859-1" encoded [not any more with TC 4.1.18
// destinationUri =
WebdavUtils.decodeURL(WebdavUtils.fixTomcatURL(destinationUri, "ISO-8859-1"));
uri = WebdavUtils.decodeURL(uri);
-
+
String contextPath = req.getContextPath();
if ((contextPath != null) && (uri.startsWith(contextPath))) {
uri = uri.substring(contextPath.length());
}
-
+
String pathInfo = req.getPathInfo();
if (pathInfo != null) {
String servletPath = req.getServletPath();
@@ -565,14 +588,14 @@
}
}
uri = getConfig().getScope() + uri;
-
+
return uri;
}
-
+
protected Element parseRequestContent(String rootName) throws JDOMException,
IOException {
Document document;
Element root;
-
+
document = parseRequestContent();
if (document == null) {
throw new JDOMException("Request content missing");
@@ -584,7 +607,7 @@
}
return root;
}
-
+
/**
* Parses the request content (XML) Document.
*
@@ -594,15 +617,15 @@
* @throws JDOMException if parsing the document failed.
*/
protected Document parseRequestContent() throws JDOMException, IOException {
-
+
if (isRequestContentParsed) {
return requestContentDocument;
}
-
+
if (req.getContentLength() == 0) {
return requestContentDocument;
}
-
+
try {
requestContentDocument = new SAXBuilder().build(req.getInputStream());
isRequestContentParsed = true;
@@ -615,11 +638,11 @@
throw e;
}
}
-
+
return requestContentDocument;
}
-
-
+
+
/**
* Generate XML response.
*
@@ -627,8 +650,8 @@
*/
protected abstract void executeRequest()
throws WebdavException, IOException;
-
-
+
+
/**
* Simulate MS IIS5 ?
*
@@ -637,7 +660,7 @@
protected boolean isMsProprietarySupport() {
return (token.getNamespaceConfig().getParameter("ms") != null);
}
-
+
/**
* Sends a precondition vilolation response.
*
@@ -645,11 +668,11 @@
* precondition.
*/
protected void sendPreconditionViolation(PreconditionViolationException pve)
throws IOException {
-
+
if (pve != null) {
-
+
ViolatedPrecondition violatedPrecondition =
pve.getViolatedPrecondition();
-
+
int statusCode = violatedPrecondition.getStatusCode();
printStackTrace( pve, statusCode );
String statusText = WebdavStatus.getStatusText(statusCode);
@@ -678,18 +701,18 @@
* @return the absolute URL.
*/
protected String getAbsoluteURL(String uri) {
-
+
StringBuffer buffer = new StringBuffer();
buffer.append(HTTP_PROTOCOL);
buffer.append(req.getServerName());
buffer.append(":");
buffer.append(req.getServerPort());
-
+
if ( ! req.getContextPath().startsWith("/") ) {
buffer.append("/");
}
buffer.append(req.getContextPath());
-
+
if (uri != null) {
if ( !req.getContextPath().endsWith("/") && !uri.startsWith("/") ) {
buffer.append("/");
@@ -698,35 +721,35 @@
}
return buffer.toString();
}
-
+
// -------------------------------------------------------- Private Methods
-
-
+
+
/**
* Get return status based on exception type.
*/
protected int getErrorCode(Throwable ex) {
return WebdavUtils.getErrorCode(ex);
}
-
-
+
+
/**
* Get return status based on exception type.
*/
protected int getErrorCode(SlideException ex) {
return WebdavUtils.getErrorCode(ex);
}
-
-
-
+
+
+
/**
* Get return status based on exception type.
*/
protected int getErrorCode(ServiceAccessException ex) {
return WebdavUtils.getErrorCode(ex);
}
-
-
+
+
/**
* Returns the value of a boolean init parameter of the servlet.
* Default value: false.
@@ -734,8 +757,8 @@
protected boolean getBooleanInitParameter( String name ) {
return "true".equalsIgnoreCase( getConfig().getInitParameter(name) );
}
-
-
+
+
/**
* Returns the value of an integer init parameter of the servlet.
* Default value: -1.
@@ -748,14 +771,14 @@
catch( NumberFormatException x ) {};
return result;
}
-
+
/**
* Error handling routine
*/
protected void sendError( int statusCode ) {
try { resp.sendError( statusCode ); } catch( Throwable x ) {};
}
-
+
/**
* Error handling routine
*/
@@ -767,7 +790,7 @@
: "");
try { resp.sendError( statusCode, statusText ); } catch( Throwable x ) {};
}
-
+
/**
* Error handling routine
*/
@@ -777,7 +800,7 @@
Messages.format( message, args );
try { resp.sendError( statusCode, statusText ); } catch( Throwable x ) {};
}
-
+
/**
* Error handling routine
*/
@@ -791,7 +814,7 @@
WebdavStatus.getStatusText(statusCode)+": "+explanation;
try { resp.sendError( statusCode, statusText ); } catch( Throwable x ) {};
}
-
+
/**
* Prints the stack trace of the given exception if the specified status code
* is greater-or-equal the value of the servlet init-parameter printStackTrace.
@@ -805,8 +828,8 @@
if( statusCode >= printStackTraceFrom )
x.printStackTrace();
}
-
-
+
+
/**
* Generate status text.
*
@@ -815,7 +838,7 @@
* @param statusCode HTTP status code of the error
*/
protected void generateStatusText(Element parentElement, String href, int
statusCode) {
-
+
Element hrefElement = new Element(E_HREF, DNSP);
parentElement.addContent(hrefElement);
hrefElement.setText(getFullPath(href));
@@ -824,7 +847,7 @@
statusElement.setText("HTTP/1.1 " + statusCode + " "
+ WebdavStatus.getStatusText(statusCode));
}
-
+
/**
* Generate an XML error message.
*
@@ -833,13 +856,13 @@
*/
protected String generateErrorMessage
(NestedSlideException nestedException) {
-
+
Element multistatus = new Element(E_MULTISTATUS, DNSP);
-
+
Enumeration nestedExceptionsList =
nestedException.enumerateExceptions();
while (nestedExceptionsList.hasMoreElements()) {
-
+
Element response = new Element(E_RESPONSE, DNSP);
multistatus.addContent(response);
SlideException ex =
@@ -849,9 +872,9 @@
if (ex instanceof PreconditionViolationException) {
response.addContent(MethodUtil.getPreconditionViolationResponseDescription((PreconditionViolationException)ex));
}
-
+
}
-
+
StringWriter stringWriter = new StringWriter();
try {
new XMLOutputter().output(multistatus, stringWriter);
@@ -860,13 +883,13 @@
Domain.log(e);
}
return stringWriter.toString();
-
+
}
-
+
protected boolean exists( String uriStr ) throws SlideException {
// use a non-blocking slide token.
SlideToken stoken = readonlySlideToken();
-
+
boolean destinationExists = true;
try {
@@ -877,11 +900,11 @@
}
return destinationExists;
}
-
+
protected boolean isLocked( String uriStr ) throws ServiceAccessException {
// use a non-blocking slide token.
SlideToken stoken = readonlySlideToken();
-
+
boolean isLocked = false;
try {
Enumeration locks = lock.enumerateLocks (stoken, uriStr, false);
@@ -899,11 +922,11 @@
}
return isLocked;
}
-
+
protected boolean isLockNull( String uriStr ) throws ServiceAccessException {
// use a non-blocking slide token.
SlideToken stoken = readonlySlideToken();
-
+
boolean isLockNull = false;
try {
NodeRevisionDescriptor nrd =
@@ -918,11 +941,11 @@
}
return isLockNull;
}
-
+
protected boolean isLockNull( NodeRevisionDescriptor nrd ) {
return nrd.propertyValueContains(P_RESOURCETYPE, E_LOCKNULL);
}
-
+
protected SlideToken readonlySlideToken() {
SlideToken stoken = slideToken;
if (stoken.isForceStoreEnlistment()) {
@@ -930,7 +953,239 @@
}
return stoken;
}
-
+
+ /**
+ * Check if the conditions specified in the optional If headers are
+ * satisfied.
+ *
+ * @param request The servlet request we are processing
+ * @param response The servlet response we are creating
+ * @param resourceInfo File object
+ * @return boolean true if the resource meets all the specified conditions,
+ * and false if any of the conditions is not satisfied, in which case
+ * request processing is stopped
+ */
+ protected boolean checkIfHeaders(HttpServletRequest request,
+ HttpServletResponse response,
+ ResourceInfo resourceInfo)
+ throws IOException {
+
+ String eTag = getETag(resourceInfo, true);
+ long fileLength = resourceInfo.length;
+ long lastModified = resourceInfo.date;
+
+ StringTokenizer commaTokenizer;
+
+ String headerValue;
+
+ // Checking If-Match
+ headerValue = request.getHeader("If-Match");
+ if (headerValue != null) {
+ if (headerValue.indexOf("*") == -1) {
+
+ commaTokenizer = new StringTokenizer(headerValue, ",");
+ boolean conditionSatisfied = false;
+
+ while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
+ String currentToken = commaTokenizer.nextToken();
+ if (currentToken.trim().equals(eTag))
+ conditionSatisfied = true;
+ }
+
+ // If none of the given ETags match, 412 Precodition failed is
+ // sent back
+ if (!conditionSatisfied) {
+ response.sendError
+ (HttpServletResponse.SC_PRECONDITION_FAILED);
+ return false;
+ }
+
+ }
+ }
+
+ // Checking If-Modified-Since
+ headerValue = request.getHeader("If-Modified-Since");
+ if (headerValue != null) {
+
+ // If an If-None-Match header has been specified, if modified since
+ // is ignored.
+ if (request.getHeader("If-None-Match") == null) {
+
+ Date date = null;
+
+ // Parsing the HTTP Date
+ for (int i = 0; (date == null) && (i < formats.length); i++) {
+ try {
+ synchronized (formats[i]) {
+ date = formats[i].parse(headerValue);
+ }
+ } catch (ParseException e) {
+ ;
+ }
+ }
+
+ if ((date != null)
+ && (lastModified <= (date.getTime() + 1000)) ) {
+ // The entity has not been modified since the date
+ // specified by the client. This is not an error case.
+ response.sendError
+ (HttpServletResponse.SC_NOT_MODIFIED);
+ return false;
+ }
+
+ }
+
+ }
+
+ // Checking If-None-Match
+ headerValue = request.getHeader("If-None-Match");
+ if (headerValue != null) {
+ if (headerValue.indexOf("*") == -1) {
+
+ commaTokenizer = new StringTokenizer(headerValue, ",");
+ boolean conditionSatisfied = true;
+
+ while (conditionSatisfied && commaTokenizer.hasMoreTokens()) {
+ String currentToken = commaTokenizer.nextToken();
+ if (currentToken.trim().equals(eTag))
+ conditionSatisfied = false;
+ }
+
+ if (conditionSatisfied) {
+
+ // For GET and HEAD, we should respond with
+ // 304 Not Modified.
+ // For every other method, 412 Precondition Failed is sent
+ // back.
+ if ( ("GET".equals(request.getMethod()))
+ || ("HEAD".equals(request.getMethod())) ) {
+ response.sendError
+ (HttpServletResponse.SC_NOT_MODIFIED);
+ return false;
+ } else {
+ response.sendError
+ (HttpServletResponse.SC_PRECONDITION_FAILED);
+ return false;
+ }
+ }
+
+ } else {
+ if (resourceInfo.exists()) {
+ return false;
+ }
+ }
+ }
+
+ // Checking If-Unmodified-Since
+ headerValue = request.getHeader("If-Unmodified-Since");
+ if (headerValue != null) {
+
+ Date date = null;
+
+ // Parsing the HTTP Date
+ for (int i = 0; (date == null) && (i < formats.length); i++) {
+ try {
+ synchronized (formats[i]) {
+ date = formats[i].parse(headerValue);
+ }
+ } catch (ParseException e) {
+ ;
+ }
+ }
+
+ if ( (date != null) && (lastModified > date.getTime()) ) {
+ // The entity has not been modified since the date
+ // specified by the client. This is not an error case.
+ response.sendError
+ (HttpServletResponse.SC_PRECONDITION_FAILED);
+ return false;
+ }
+
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the ETag value associated with a file.
+ *
+ * @param resourceInfo File object
+ * @param strong True if we want a strong ETag, in which case a checksum
+ * of the file has to be calculated
+ */
+ protected String getETagValue(ResourceInfo resourceInfo, boolean strong) {
+ // FIXME : Compute a strong ETag if requested, using an MD5 digest
+ // of the file contents
+ if (resourceInfo.exists()) {
+ return resourceInfo.etag;
+ }
+ else {
+ return resourceInfo.length + "-" + resourceInfo.date;
+ }
+ }
+
+
+ /**
+ * Get the ETag associated with a file.
+ *
+ * @param resourceInfo File object
+ * @param strong True if we want a strong ETag, in which case a checksum
+ * of the file has to be calculated
+ */
+ protected String getETag(ResourceInfo resourceInfo, boolean strong) {
+ if (strong)
+ return "\"" + getETagValue(resourceInfo, strong) + "\"";
+ else
+ return "W/\"" + getETagValue(resourceInfo, strong) + "\"";
+ }
+
+ protected class ResourceInfo {
+
+ /**
+ * Constructor.
+ *
+ * @param pathname Path name of the file
+ */
+ public ResourceInfo(String path, NodeRevisionDescriptor properties) {
+
+ this.path = path;
+ this.exists = true;
+ this.creationDate = properties.getCreationDateAsDate().getTime();
+ this.date = properties.getLastModifiedAsDate().getTime();
+ this.httpDate = properties.getLastModified();
+ this.length = properties.getContentLength();
+ this.etag = properties.getETag();
+
+ }
+
+
+ public String path;
+ public long creationDate;
+ public String httpDate;
+ public long date;
+ public long length;
+ public String etag;
+ //public boolean collection;
+ public boolean exists;
+
+
+ /**
+ * Test if the associated resource exists.
+ */
+ public boolean exists() {
+ return exists;
+ }
+
+
+ /**
+ * String representation.
+ */
+ public String toString() {
+ return path;
+ }
+
+
+ }
protected class RequestHeaders {
private static final int
@@ -1398,6 +1653,7 @@
}
}
}
+
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]