pnever 2003/08/17 23:55:09
Modified: src/webdav/server/org/apache/slide/webdav/method
AbstractWebdavMethod.java
Log:
Added convenience methods and minor issues
Revision Changes Path
1.11 +247 -192
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.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- AbstractWebdavMethod.java 22 May 2003 15:06:11 -0000 1.10
+++ AbstractWebdavMethod.java 18 Aug 2003 06:55:09 -0000 1.11
@@ -69,6 +69,7 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
+import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.slide.common.Domain;
@@ -78,8 +79,11 @@
import org.apache.slide.common.SlideException;
import org.apache.slide.common.SlideToken;
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.lock.Lock;
import org.apache.slide.lock.ObjectLockedException;
import org.apache.slide.lock.UnlockListener;
@@ -89,7 +93,9 @@
import org.apache.slide.search.Search;
import org.apache.slide.security.AccessDeniedException;
import org.apache.slide.security.Security;
+import org.apache.slide.structure.LinkedObjectNotFoundException;
import org.apache.slide.structure.ObjectAlreadyExistsException;
+import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.structure.Structure;
import org.apache.slide.util.Messages;
@@ -97,11 +103,13 @@
import org.apache.slide.webdav.WebdavException;
import org.apache.slide.webdav.WebdavMethod;
import org.apache.slide.webdav.WebdavServletConfig;
+import org.apache.slide.webdav.util.BindConstants;
import org.apache.slide.webdav.util.PreconditionViolationException;
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.slide.webdav.util.XMLValue;
import org.apache.util.MD5Encoder;
import org.apache.util.WebdavStatus;
import org.jdom.Document;
@@ -117,159 +125,157 @@
* @author Christopher Lenz
*/
public abstract class AbstractWebdavMethod
- implements WebdavMethod, WebdavConstants {
-
-
+ implements WebdavMethod, WebdavConstants, BindConstants {
+
+
// -------------------------------------------------------------- Constants
-
+
/**
* String constant for <code>no-cache</code>.
*/
protected static final String NO_CACHE = "no-cache";
-
+
/**
* String constant for <code>http://</code>.
*/
public static final String HTTP_PROTOCOL = "http://";
-
+
/**
* String constant for <code>HTTP/1.1</code>.
*/
public static final String HTTP_VERSION = "HTTP/1.1";
-
+
/**
* String constant for <code>text/xml</code>.
*/
public static final String TEXT_XML = "text/xml";
-
+
/**
* String constant for <code>text/xml; charset="UTF-8"</code>.
*/
public static final String TEXT_XML_UTF_8 = "text/xml; charset=\"UTF-8\"";
-
+
/**
* The indent to use in the XML response.
*/
public static final String XML_REPONSE_INDENT = " ";
-
-
+
+
private static final String LOG_CHANNEL =
AbstractWebdavMethod.class.getName();
-
- public static final String LOCK_TOKEN = "opaquelocktoken:";
-
-// public static final String PRINCIPAL =
-// "org.apache.slide.webdav.method.principal";
-
-
+
+ // public static final String PRINCIPAL =
+ // "org.apache.slide.webdav.method.principal";
+
+
// ----------------------------------------------------- Instance Variables
-
-
+
+
/**
* Requested Uri.
*/
protected String requestUri;
-
-
+
+
/**
* Servlet request.
*/
protected HttpServletRequest req;
-
-
+
+
/**
* Servlet response.
*/
protected HttpServletResponse resp;
-
-
+
+
/**
* Configuration.
*/
protected WebdavServletConfig config;
-
-
+
+
/**
* Request body.
*/
protected String requestBody;
-
-
+
+
/**
* Namespace access token.
*/
protected NamespaceAccessToken token;
-
-
+
+
/**
* Structure helper.
*/
protected Structure structure;
-
-
+
+
/**
* Content helper.
*/
protected Content content;
-
-
+
+
/**
* Security helper.
*/
protected Security security;
-
-
+
+
/**
* Lock helper.
*/
protected Lock lock;
-
-
+
+
/** wam
* Search helper.
*/
protected Search search;
-
-
+
+
/**
* Macro helper.
*/
protected Macro macro;
-
-
+
+
/**
* Slide token.
*/
protected SlideToken slideToken;
-
-
+
+
/**
* MD5 message digest provider.
*/
protected static MessageDigest md5Helper;
-
-
+
+
/**
* The MD5 helper object for this class.
*/
protected static final MD5Encoder md5Encoder = new MD5Encoder();
-
+
/**
* The request content (XML) Document.
*/
private Document requestContentDocument = null;
-
+
/**
* Indicates if the request content has already been parsed.
*/
private boolean isRequestContentParsed = false;
-
-
+
+
// -------------------------------------------------- Static Initialization
-
-
+
+
static {
-
+
// Load the MD5 helper used to calculate signatures.
try {
md5Helper = MessageDigest.getInstance("MD5");
@@ -278,11 +284,11 @@
throw new IllegalStateException();
}
}
-
-
+
+
// ----------------------------------------------------------- Constructors
-
-
+
+
/**
* Constructor.
*
@@ -291,10 +297,10 @@
*/
public AbstractWebdavMethod(NamespaceAccessToken token,
WebdavServletConfig config) {
-
+
this.config = config;
this.token = token;
-
+
// initialize helpers
structure = token.getStructureHelper();
content = token.getContentHelper();
@@ -302,11 +308,11 @@
lock = token.getLockHelper();
macro = token.getMacroHelper();
}
-
-
+
+
// -------------------------------------------- WebdavMethod Implementation
-
-
+
+
/**
* Exceute method.
*
@@ -314,13 +320,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);
parseHeaders();
-
+
boolean transactionIsStarted = false;
try {
parseRequest();
@@ -328,7 +334,7 @@
token.begin();
transactionIsStarted = true;
}
-
+
// clear expired lock-tokens
try {
UnlockListener listener =
@@ -336,7 +342,7 @@
lock.clearExpiredLocks( slideToken, requestUri, listener );
}
catch (SlideException e) {}
-
+
executeRequest();
if (methodNeedsTransactionSupport()) {
token.commit();
@@ -359,37 +365,37 @@
}
}
}
-
+
}
-
-
+
+
// --------------------------------------------------------- Public Methods
-
-
+
+
/**
* Returns the configuration of the WebdavServlet.
*
* @return WebdavServletConfig
*/
public WebdavServletConfig getConfig() {
-
+
return config;
}
-
-
+
+
/**
* Return an absolute URL (absolute in the HTTP sense) based on a Slide
* path.
*/
public String getFullPath(String path) {
-
+
if (path.startsWith("/"))
return WebdavUtils.encodeURL(req.getContextPath() + path);
else
return WebdavUtils.encodeURL(req.getContextPath() + "/" + path);
}
-
-
+
+
/**
* Returns a Slide path based on an absolute URL
* (absolute in the HTTP sense)
@@ -400,7 +406,7 @@
fullpath=fullpath.substring(fullpath.indexOf("://")+3);
fullpath=fullpath.substring(fullpath.indexOf("/"));
}
-
+
// strip off the servlet context path
String contextPath=req.getContextPath();
if (fullpath.startsWith(contextPath)) {
@@ -408,11 +414,11 @@
}
return fullpath;
}
-
-
+
+
// ------------------------------------------------------ Protected Methods
-
-
+
+
/**
* Return true if the method needs transaction support.
* Return true if the method needs transaction support, e.g.
@@ -425,8 +431,8 @@
// overwrite it to true, but PropFind creates a RevisionDescriptors
// on the fly
}
-
-
+
+
/**
* Read request contents.
*
@@ -434,12 +440,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()));
@@ -448,9 +454,9 @@
token.getLogger().log(e,LOG_CHANNEL,Logger.ERROR);
}
}
-
-
-
+
+
+
/**
* Translate the encoding string into a proper Java encoding String.
*/
@@ -461,28 +467,28 @@
if (result.endsWith("\"")) result = result.substring(0,
result.length()-1);
return result;
}
-
-
+
+
/**
* Parse lock token headers.
*/
protected void parseHeaders() {
-
+
// Retrieve if header
String ifHeader = req.getHeader("If");
//System.out.println("If header : " + ifHeader);
-
+
if (ifHeader == null)
return;
-
+
// Parse if header and extract the lock tokens
- int pos = ifHeader.indexOf(LOCK_TOKEN);
+ int pos = ifHeader.indexOf(S_LOCK_TOKEN);
int endPos = -1;
- int offset = LOCK_TOKEN.length();
+ int offset = S_LOCK_TOKEN.length();
String lockToken = null;
-
+
while (pos != -1) {
-
+
endPos = ifHeader.indexOf('>', pos + offset);
if (endPos == -1) {
lockToken = ifHeader;
@@ -490,17 +496,17 @@
} else {
lockToken = ifHeader.substring(pos + offset, endPos);
}
-
+
//System.out.println("Lock Token found :-" + lockToken + "-");
slideToken.addLockToken(lockToken);
-
- pos = ifHeader.indexOf(LOCK_TOKEN, endPos);
-
+
+ pos = ifHeader.indexOf(S_LOCK_TOKEN, endPos);
+
}
-
+
}
-
-
+
+
/**
* Returns the lock token value from the lock token header.
*
@@ -517,15 +523,54 @@
}
return result;
}
-
+
/**
* 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
+ *
+ * @param lowerNode an ObjectNode
+ * @param upperNode an ObjectNode
+ *
+ * @return true, if lowerNode is below upperNode in the namespace
+ *
+ */
+ protected boolean isDescendant( ObjectNode lowerNode, ObjectNode upperNode ) {
+ if (lowerNode.getUuri().equals(upperNode.getUuri())) {
+ return true;
+ }
+ if (upperNode.hasBinding(lowerNode)) {
+ return true;
+ }
+
+ NodeRevisionDescriptors lowerNrds = null;
+ NodeRevisionDescriptor lowerNrd = null;
+ try {
+ lowerNrds = content.retrieve(slideToken, lowerNode.getUri());
+ lowerNrd = content.retrieve(slideToken, lowerNrds);
+
+ NodeProperty psProp = lowerNrd.getProperty(P_PARENT_SET);
+ XMLValue xv = new XMLValue( String.valueOf(psProp.getValue()) );
+ Iterator i = xv.getList().iterator();
+ while (i.hasNext()) {
+ // iterate over parent elements
+ Element pElm = (Element)i.next();
+ String hrPath = pElm.getChild( E_HREF,
NamespaceCache.DEFAULT_NAMESPACE ).getText();
+ ObjectNode hrNode = structure.retrieve( slideToken, hrPath );
+ return isDescendant( hrNode, upperNode );
+ }
+ } catch (Exception e) {}
+
+ return false;
+ }
+
+
/**
* Parse WebDAV XML query.
*
@@ -533,9 +578,9 @@
*/
protected abstract void parseRequest()
throws WebdavException;
-
-
-
+
+
+
/**
* Returns the request content (XML) Document.
*
@@ -544,9 +589,9 @@
protected Document getRequestContent() {
return requestContentDocument;
}
-
+
//--
-
+
/**
* precondition: sourceUri != null
*/
@@ -567,12 +612,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) {
@@ -582,16 +627,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();
@@ -600,14 +645,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");
@@ -619,7 +664,7 @@
}
return root;
}
-
+
/**
* Parses the request content (XML) Document.
*
@@ -629,11 +674,11 @@
* @throws JDOMException if parsing the document failed.
*/
protected Document parseRequestContent() throws JDOMException, IOException {
-
+
if (isRequestContentParsed) {
return requestContentDocument;
}
-
+
if (requestBody == null) {
readRequestContent();
if (requestBody == null) {
@@ -654,11 +699,11 @@
throw e;
}
}
-
+
return requestContentDocument;
}
-
-
+
+
/**
* Generate XML response.
*
@@ -666,8 +711,8 @@
*/
protected abstract void executeRequest()
throws WebdavException, IOException;
-
-
+
+
/**
* Simulate MS IIS5 ?
*
@@ -676,7 +721,7 @@
protected boolean isMsProprietarySupport() {
return (token.getNamespaceConfig().getParameter("ms") != null);
}
-
+
/**
* Sends a precondition vilolation response.
*
@@ -684,21 +729,21 @@
* precondition.
*/
protected void sendPreconditionViolation(PreconditionViolationException pve)
throws IOException {
-
+
if (pve != null) {
-
+
ViolatedPrecondition violatedPrecondition =
pve.getViolatedPrecondition();
-
+
int statusCode = violatedPrecondition.getStatusCode();
printStackTrace( pve, statusCode );
resp.setStatus( statusCode );
resp.setContentType(TEXT_XML_UTF_8);
-
+
new XMLOutputter(XML_REPONSE_INDENT, true).
output(new
Document(MethodUtil.getPreconditionViolationError(pve.getViolatedPrecondition())),
resp.getWriter());
}
}
-
+
/**
* Returns the absolute URL of the given <code>uri</code>, e.g.
* if the server is <code>aloha.com:80</code>, context path is
@@ -710,18 +755,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("/");
@@ -730,23 +775,23 @@
}
return buffer.toString();
}
-
+
// -------------------------------------------------------- Private Methods
-
-
+
+
/**
* Get return status based on exception type.
*/
protected int getErrorCode(Throwable ex) {
if ( !(ex instanceof SlideException) ) {
-// if( ex != null ) ex.printStackTrace();
+ // if( ex != null ) ex.printStackTrace();
return WebdavStatus.SC_INTERNAL_SERVER_ERROR;
} else {
return getErrorCode((SlideException)ex);
}
}
-
-
+
+
/**
* Get return status based on exception type.
*/
@@ -772,28 +817,28 @@
} catch(MethodNotAllowedException e) {
return WebdavStatus.SC_METHOD_NOT_ALLOWED;
} catch(SlideException e) {
-// e.printStackTrace();
+ // e.printStackTrace();
return WebdavStatus.SC_INTERNAL_SERVER_ERROR;
}
}
-
-
-
+
+
+
/**
* Get return status based on exception type.
*/
protected int getErrorCode(ServiceAccessException ex) {
Throwable cause = ex.getCauseException();
if (cause == null || !(cause instanceof SlideException) ) {
-// ex.printStackTrace();
+ // ex.printStackTrace();
if( cause != null ) cause.printStackTrace();
return WebdavStatus.SC_INTERNAL_SERVER_ERROR; // this is the default}
} else {
return getErrorCode((SlideException)cause);
}
}
-
-
+
+
/**
* Returns the value of a boolean init parameter of the servlet.
* Default value: false.
@@ -801,8 +846,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.
@@ -815,14 +860,14 @@
catch( NumberFormatException x ) {};
return result;
}
-
+
/**
* Error handling routine
*/
protected void sendError( int statusCode ) {
try { resp.sendError( statusCode ); } catch( Throwable x ) {};
}
-
+
/**
* Error handling routine
*/
@@ -832,7 +877,7 @@
Messages.format( message, (Object)null );
try { resp.sendError( statusCode, statusText ); } catch( Throwable x ) {};
}
-
+
/**
* Error handling routine
*/
@@ -842,21 +887,21 @@
Messages.format( message, args );
try { resp.sendError( statusCode, statusText ); } catch( Throwable x ) {};
}
-
+
/**
* Error handling routine
*/
protected void sendError( int statusCode, Throwable t ) {
printStackTrace( t, statusCode );
String explanation = (t == null || t.getMessage() == null ||
"".equals(t.getMessage())
- ? Messages.format(t.getClass().getName(), (Object)null)
- : t.getMessage()
- );
+ ? Messages.format(t.getClass().getName(),
(Object)null)
+ : t.getMessage()
+ );
String statusText =
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.
@@ -870,8 +915,8 @@
if( statusCode >= printStackTraceFrom )
x.printStackTrace();
}
-
-
+
+
/**
* Generate status text.
*
@@ -880,7 +925,7 @@
* @param statusCode HTTP status code of the error
*/
protected void generateStatusText(Element parentElement, String href, int
statusCode) {
-
+
Element hrefElement = new Element(E_HREF, NamespaceCache.DEFAULT_NAMESPACE);
parentElement.addContent(hrefElement);
hrefElement.setText(getFullPath(href));
@@ -889,7 +934,7 @@
statusElement.setText("HTTP/1.1 " + statusCode + " "
+ WebdavStatus.getStatusText(statusCode));
}
-
+
/**
* Generate an XML error message.
*
@@ -898,13 +943,13 @@
*/
protected String generateErrorMessage
(NestedSlideException nestedException) {
-
+
Element multistatus = new Element(E_MULTISTATUS,
NamespaceCache.DEFAULT_NAMESPACE);
-
+
Enumeration nestedExceptionsList =
nestedException.enumerateExceptions();
while (nestedExceptionsList.hasMoreElements()) {
-
+
Element response = new Element(E_RESPONSE,
NamespaceCache.DEFAULT_NAMESPACE);
multistatus.addContent(response);
SlideException ex =
@@ -914,9 +959,9 @@
if (ex instanceof PreconditionViolationException) {
response.addContent(MethodUtil.getPreconditionViolationResponseDescription((PreconditionViolationException)ex));
}
-
+
}
-
+
StringWriter stringWriter = new StringWriter();
try {
new XMLOutputter().output(multistatus, stringWriter);
@@ -925,23 +970,33 @@
Domain.log(e);
}
return stringWriter.toString();
-
+
}
-
- protected PreconditionViolationException preconditionViolation(String msg,
String arg) {
- // According to JPL, the error code for precondition violations it not
specified in the
- // spec. We return an error code that indicates a permanent failure, i.e.
re-submitting the
- // request doesn't help
- final int DONT_RETRY = WebdavStatus.SC_FORBIDDEN;
-
- PreconditionViolationException ex;
-
- ex = new PreconditionViolationException(new ViolatedPrecondition(msg,
DONT_RETRY), arg);
- sendError( DONT_RETRY, ex );
- return ex;
+
+ protected boolean exists( String uriStr ) throws SlideException {
+ boolean destinationExists = true;
+ try {
+ content.retrieve(slideToken, uriStr);
+ }
+ catch (ObjectNotFoundException x) {
+ destinationExists = false;
+ }
+ return destinationExists;
}
-
-
+
+ protected boolean isLockNull( String uriStr ) throws SlideException {
+ boolean isLockNull = false;
+ try {
+ NodeRevisionDescriptor nrd =
+ content.retrieve(slideToken, content.retrieve(slideToken, uriStr));
+ isLockNull = nrd.propertyValueContains(P_RESOURCETYPE, "lock-null");
+ }
+ catch (ObjectNotFoundException x) {
+ // ignore silently
+ }
+ return isLockNull;
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]