WebdavServletpublic class WebdavServlet extends DefaultServlet Servlet which adds support for WebDAV level 2. All the basic HTTP requests
are handled by the DefaultServlet. |
Fields Summary |
---|
private static final String | METHOD_HEAD | private static final String | METHOD_PROPFIND | private static final String | METHOD_PROPPATCH | private static final String | METHOD_MKCOL | private static final String | METHOD_COPY | private static final String | METHOD_MOVE | private static final String | METHOD_LOCK | private static final String | METHOD_UNLOCK | private static final int | INFINITYDefault depth is infite. | private static final int | FIND_BY_PROPERTYPROPFIND - Specify a property mask. | private static final int | FIND_ALL_PROPPROPFIND - Display all properties. | private static final int | FIND_PROPERTY_NAMESPROPFIND - Return property names. | private static final int | LOCK_CREATIONCreate a new lock. | private static final int | LOCK_REFRESHRefresh lock. | private static final int | DEFAULT_TIMEOUTDefault lock timeout value. | private static final int | MAX_TIMEOUTMaximum lock timeout. | protected static final String | DEFAULT_NAMESPACEDefault namespace. | protected static final SimpleDateFormat | creationDateFormatSimple date format for the creation date ISO representation (partial). | protected static MessageDigest | md5HelperMD5 message digest provider. | protected static final org.apache.catalina.util.MD5Encoder | md5EncoderThe MD5 helper object for this class. | private Hashtable | resourceLocksRepository of the locks put on single resources.
Key : path
Value : LockInfo | private Hashtable | lockNullResourcesRepository of the lock-null resources.
Key : path of the collection containing the lock-null resource
Value : Vector of lock-null resource which are members of the
collection. Each element of the Vector is the path associated with
the lock-null resource. | private Vector | collectionLocksVector of the heritable locks.
Key : path
Value : LockInfo | private String | secretSecret information used to generate reasonably secure lock ids. |
Methods Summary |
---|
protected boolean | checkIfHeaders(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, org.apache.naming.resources.ResourceAttributes resourceAttributes)Check if the conditions specified in the optional If headers are
satisfied.
if (!super.checkIfHeaders(request, response, resourceAttributes))
return false;
// TODO : Checking the WebDAV If header
return true;
| private boolean | copyResource(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)Copy a resource.
// Parsing destination header
String destinationPath = req.getHeader("Destination");
if (destinationPath == null) {
resp.sendError(WebdavStatus.SC_BAD_REQUEST);
return false;
}
// Remove url encoding from destination
destinationPath = RequestUtil.URLDecode(destinationPath, "UTF8");
int protocolIndex = destinationPath.indexOf("://");
if (protocolIndex >= 0) {
// if the Destination URL contains the protocol, we can safely
// trim everything upto the first "/" character after "://"
int firstSeparator =
destinationPath.indexOf("/", protocolIndex + 4);
if (firstSeparator < 0) {
destinationPath = "/";
} else {
destinationPath = destinationPath.substring(firstSeparator);
}
} else {
String hostName = req.getServerName();
if ((hostName != null) && (destinationPath.startsWith(hostName))) {
destinationPath = destinationPath.substring(hostName.length());
}
int portIndex = destinationPath.indexOf(":");
if (portIndex >= 0) {
destinationPath = destinationPath.substring(portIndex);
}
if (destinationPath.startsWith(":")) {
int firstSeparator = destinationPath.indexOf("/");
if (firstSeparator < 0) {
destinationPath = "/";
} else {
destinationPath =
destinationPath.substring(firstSeparator);
}
}
}
// Normalise destination path (remove '.' and '..')
destinationPath = normalize(destinationPath);
String contextPath = req.getContextPath();
if ((contextPath != null) &&
(destinationPath.startsWith(contextPath))) {
destinationPath = destinationPath.substring(contextPath.length());
}
String pathInfo = req.getPathInfo();
if (pathInfo != null) {
String servletPath = req.getServletPath();
if ((servletPath != null) &&
(destinationPath.startsWith(servletPath))) {
destinationPath = destinationPath
.substring(servletPath.length());
}
}
if (debug > 0)
log("Dest path :" + destinationPath);
if ((destinationPath.toUpperCase().startsWith("/WEB-INF")) ||
(destinationPath.toUpperCase().startsWith("/META-INF"))) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return false;
}
String path = getRelativePath(req);
if ((path.toUpperCase().startsWith("/WEB-INF")) ||
(path.toUpperCase().startsWith("/META-INF"))) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return false;
}
if (destinationPath.equals(path)) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return false;
}
// Parsing overwrite header
boolean overwrite = true;
String overwriteHeader = req.getHeader("Overwrite");
if (overwriteHeader != null) {
if (overwriteHeader.equalsIgnoreCase("T")) {
overwrite = true;
} else {
overwrite = false;
}
}
// Overwriting the destination
boolean exists = true;
try {
resources.lookup(destinationPath);
} catch (NamingException e) {
exists = false;
}
if (overwrite) {
// Delete destination resource, if it exists
if (exists) {
if (!deleteResource(destinationPath, req, resp, true)) {
return false;
}
} else {
resp.setStatus(WebdavStatus.SC_CREATED);
}
} else {
// If the destination exists, then it's a conflict
if (exists) {
resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
return false;
}
}
// Copying source to destination
Hashtable<String,Integer> errorList = new Hashtable<String,Integer>();
boolean result = copyResource(resources, errorList,
path, destinationPath);
if ((!result) || (!errorList.isEmpty())) {
sendReport(req, resp, errorList);
return false;
}
// Removing any lock-null resource which would be present at
// the destination path
lockNullResources.remove(destinationPath);
return true;
| private boolean | copyResource(javax.naming.directory.DirContext resources, java.util.Hashtable errorList, java.lang.String source, java.lang.String dest)Copy a collection.
if (debug > 1)
log("Copy: " + source + " To: " + dest);
Object object = null;
try {
object = resources.lookup(source);
} catch (NamingException e) {
}
if (object instanceof DirContext) {
try {
resources.createSubcontext(dest);
} catch (NamingException e) {
errorList.put
(dest, new Integer(WebdavStatus.SC_CONFLICT));
return false;
}
try {
NamingEnumeration enumeration = resources.list(source);
while (enumeration.hasMoreElements()) {
NameClassPair ncPair = (NameClassPair) enumeration.nextElement();
String childDest = dest;
if (!childDest.equals("/"))
childDest += "/";
childDest += ncPair.getName();
String childSrc = source;
if (!childSrc.equals("/"))
childSrc += "/";
childSrc += ncPair.getName();
copyResource(resources, errorList, childSrc, childDest);
}
} catch (NamingException e) {
errorList.put
(dest, new Integer(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
return false;
}
} else {
if (object instanceof Resource) {
try {
resources.bind(dest, object);
} catch (NamingException e) {
errorList.put
(source,
new Integer(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
return false;
}
} else {
errorList.put
(source,
new Integer(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
return false;
}
}
return true;
| private void | deleteCollection(javax.servlet.http.HttpServletRequest req, javax.naming.directory.DirContext resources, java.lang.String path, java.util.Hashtable errorList)Deletes a collection.
if (debug > 1)
log("Delete:" + path);
if ((path.toUpperCase().startsWith("/WEB-INF")) ||
(path.toUpperCase().startsWith("/META-INF"))) {
errorList.put(path, new Integer(WebdavStatus.SC_FORBIDDEN));
return;
}
String ifHeader = req.getHeader("If");
if (ifHeader == null)
ifHeader = "";
String lockTokenHeader = req.getHeader("Lock-Token");
if (lockTokenHeader == null)
lockTokenHeader = "";
Enumeration enumeration = null;
try {
enumeration = resources.list(path);
} catch (NamingException e) {
errorList.put(path, new Integer
(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
return;
}
while (enumeration.hasMoreElements()) {
NameClassPair ncPair = (NameClassPair) enumeration.nextElement();
String childName = path;
if (!childName.equals("/"))
childName += "/";
childName += ncPair.getName();
if (isLocked(childName, ifHeader + lockTokenHeader)) {
errorList.put(childName, new Integer(WebdavStatus.SC_LOCKED));
} else {
try {
Object object = resources.lookup(childName);
if (object instanceof DirContext) {
deleteCollection(req, resources, childName, errorList);
}
try {
resources.unbind(childName);
} catch (NamingException e) {
if (!(object instanceof DirContext)) {
// If it's not a collection, then it's an unknown
// error
errorList.put
(childName, new Integer
(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
}
}
} catch (NamingException e) {
errorList.put
(childName, new Integer
(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
}
}
}
| private boolean | deleteResource(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)Delete a resource.
String path = getRelativePath(req);
return deleteResource(path, req, resp, true);
| private boolean | deleteResource(java.lang.String path, javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp, boolean setStatus)Delete a resource.
if ((path.toUpperCase().startsWith("/WEB-INF")) ||
(path.toUpperCase().startsWith("/META-INF"))) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return false;
}
String ifHeader = req.getHeader("If");
if (ifHeader == null)
ifHeader = "";
String lockTokenHeader = req.getHeader("Lock-Token");
if (lockTokenHeader == null)
lockTokenHeader = "";
if (isLocked(path, ifHeader + lockTokenHeader)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return false;
}
boolean exists = true;
Object object = null;
try {
object = resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
if (!exists) {
resp.sendError(WebdavStatus.SC_NOT_FOUND);
return false;
}
boolean collection = (object instanceof DirContext);
if (!collection) {
try {
resources.unbind(path);
} catch (NamingException e) {
resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
return false;
}
} else {
Hashtable<String,Integer> errorList =
new Hashtable<String,Integer>();
deleteCollection(req, resources, path, errorList);
try {
resources.unbind(path);
} catch (NamingException e) {
errorList.put(path, new Integer
(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
}
if (!errorList.isEmpty()) {
sendReport(req, resp, errorList);
return false;
}
}
if (setStatus) {
resp.setStatus(WebdavStatus.SC_NO_CONTENT);
}
return true;
| private java.lang.StringBuffer | determineMethodsAllowed(javax.naming.directory.DirContext resources, javax.servlet.http.HttpServletRequest req)Determines the methods normally allowed for the resource.
StringBuffer methodsAllowed = new StringBuffer();
boolean exists = true;
Object object = null;
try {
String path = getRelativePath(req);
object = resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
if (!exists) {
methodsAllowed.append("OPTIONS, MKCOL, PUT, LOCK");
return methodsAllowed;
}
methodsAllowed.append("OPTIONS, GET, HEAD, POST, DELETE, TRACE");
methodsAllowed.append(", PROPPATCH, COPY, MOVE, LOCK, UNLOCK");
if (listings) {
methodsAllowed.append(", PROPFIND");
}
if (!(object instanceof DirContext)) {
methodsAllowed.append(", PUT");
}
return methodsAllowed;
| protected void | doCopy(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)COPY Method.
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
copyResource(req, resp);
| protected void | doDelete(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)DELETE Method.
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
deleteResource(req, resp);
| protected void | doLock(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)LOCK Method.
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
LockInfo lock = new LockInfo();
// Parsing lock request
// Parsing depth header
String depthStr = req.getHeader("Depth");
if (depthStr == null) {
lock.depth = INFINITY;
} else {
if (depthStr.equals("0")) {
lock.depth = 0;
} else {
lock.depth = INFINITY;
}
}
// Parsing timeout header
int lockDuration = DEFAULT_TIMEOUT;
String lockDurationStr = req.getHeader("Timeout");
if (lockDurationStr == null) {
lockDuration = DEFAULT_TIMEOUT;
} else {
int commaPos = lockDurationStr.indexOf(",");
// If multiple timeouts, just use the first
if (commaPos != -1) {
lockDurationStr = lockDurationStr.substring(0,commaPos);
}
if (lockDurationStr.startsWith("Second-")) {
lockDuration =
(new Integer(lockDurationStr.substring(7))).intValue();
} else {
if (lockDurationStr.equalsIgnoreCase("infinity")) {
lockDuration = MAX_TIMEOUT;
} else {
try {
lockDuration =
(new Integer(lockDurationStr)).intValue();
} catch (NumberFormatException e) {
lockDuration = MAX_TIMEOUT;
}
}
}
if (lockDuration == 0) {
lockDuration = DEFAULT_TIMEOUT;
}
if (lockDuration > MAX_TIMEOUT) {
lockDuration = MAX_TIMEOUT;
}
}
lock.expiresAt = System.currentTimeMillis() + (lockDuration * 1000);
int lockRequestType = LOCK_CREATION;
Node lockInfoNode = null;
DocumentBuilder documentBuilder = getDocumentBuilder();
try {
Document document = documentBuilder.parse(new InputSource
(req.getInputStream()));
// Get the root element of the document
Element rootElement = document.getDocumentElement();
lockInfoNode = rootElement;
} catch (IOException e) {
lockRequestType = LOCK_REFRESH;
} catch (SAXException e) {
lockRequestType = LOCK_REFRESH;
}
if (lockInfoNode != null) {
// Reading lock information
NodeList childList = lockInfoNode.getChildNodes();
StringWriter strWriter = null;
DOMWriter domWriter = null;
Node lockScopeNode = null;
Node lockTypeNode = null;
Node lockOwnerNode = null;
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
String nodeName = currentNode.getNodeName();
if (nodeName.endsWith("lockscope")) {
lockScopeNode = currentNode;
}
if (nodeName.endsWith("locktype")) {
lockTypeNode = currentNode;
}
if (nodeName.endsWith("owner")) {
lockOwnerNode = currentNode;
}
break;
}
}
if (lockScopeNode != null) {
childList = lockScopeNode.getChildNodes();
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
String tempScope = currentNode.getNodeName();
if (tempScope.indexOf(':") != -1) {
lock.scope = tempScope.substring
(tempScope.indexOf(':") + 1);
} else {
lock.scope = tempScope;
}
break;
}
}
if (lock.scope == null) {
// Bad request
resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
}
} else {
// Bad request
resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
}
if (lockTypeNode != null) {
childList = lockTypeNode.getChildNodes();
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
String tempType = currentNode.getNodeName();
if (tempType.indexOf(':") != -1) {
lock.type =
tempType.substring(tempType.indexOf(':") + 1);
} else {
lock.type = tempType;
}
break;
}
}
if (lock.type == null) {
// Bad request
resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
}
} else {
// Bad request
resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
}
if (lockOwnerNode != null) {
childList = lockOwnerNode.getChildNodes();
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
lock.owner += currentNode.getNodeValue();
break;
case Node.ELEMENT_NODE:
strWriter = new StringWriter();
domWriter = new DOMWriter(strWriter, true);
domWriter.setQualifiedNames(false);
domWriter.print(currentNode);
lock.owner += strWriter.toString();
break;
}
}
if (lock.owner == null) {
// Bad request
resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
}
} else {
lock.owner = new String();
}
}
String path = getRelativePath(req);
lock.path = path;
boolean exists = true;
Object object = null;
try {
object = resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
Enumeration locksList = null;
if (lockRequestType == LOCK_CREATION) {
// Generating lock id
String lockTokenStr = req.getServletPath() + "-" + lock.type + "-"
+ lock.scope + "-" + req.getUserPrincipal() + "-"
+ lock.depth + "-" + lock.owner + "-" + lock.tokens + "-"
+ lock.expiresAt + "-" + System.currentTimeMillis() + "-"
+ secret;
String lockToken =
md5Encoder.encode(md5Helper.digest(lockTokenStr.getBytes()));
if ( (exists) && (object instanceof DirContext) &&
(lock.depth == INFINITY) ) {
// Locking a collection (and all its member resources)
// Checking if a child resource of this collection is
// already locked
Vector<String> lockPaths = new Vector<String>();
locksList = collectionLocks.elements();
while (locksList.hasMoreElements()) {
LockInfo currentLock = (LockInfo) locksList.nextElement();
if (currentLock.hasExpired()) {
resourceLocks.remove(currentLock.path);
continue;
}
if ( (currentLock.path.startsWith(lock.path)) &&
((currentLock.isExclusive()) ||
(lock.isExclusive())) ) {
// A child collection of this collection is locked
lockPaths.addElement(currentLock.path);
}
}
locksList = resourceLocks.elements();
while (locksList.hasMoreElements()) {
LockInfo currentLock = (LockInfo) locksList.nextElement();
if (currentLock.hasExpired()) {
resourceLocks.remove(currentLock.path);
continue;
}
if ( (currentLock.path.startsWith(lock.path)) &&
((currentLock.isExclusive()) ||
(lock.isExclusive())) ) {
// A child resource of this collection is locked
lockPaths.addElement(currentLock.path);
}
}
if (!lockPaths.isEmpty()) {
// One of the child paths was locked
// We generate a multistatus error report
Enumeration lockPathsList = lockPaths.elements();
resp.setStatus(WebdavStatus.SC_CONFLICT);
XMLWriter generatedXML = new XMLWriter();
generatedXML.writeXMLHeader();
generatedXML.writeElement
(null, "multistatus" + generateNamespaceDeclarations(),
XMLWriter.OPENING);
while (lockPathsList.hasMoreElements()) {
generatedXML.writeElement(null, "response",
XMLWriter.OPENING);
generatedXML.writeElement(null, "href",
XMLWriter.OPENING);
generatedXML
.writeText((String) lockPathsList.nextElement());
generatedXML.writeElement(null, "href",
XMLWriter.CLOSING);
generatedXML.writeElement(null, "status",
XMLWriter.OPENING);
generatedXML
.writeText("HTTP/1.1 " + WebdavStatus.SC_LOCKED
+ " " + WebdavStatus
.getStatusText(WebdavStatus.SC_LOCKED));
generatedXML.writeElement(null, "status",
XMLWriter.CLOSING);
generatedXML.writeElement(null, "response",
XMLWriter.CLOSING);
}
generatedXML.writeElement(null, "multistatus",
XMLWriter.CLOSING);
Writer writer = resp.getWriter();
writer.write(generatedXML.toString());
writer.close();
return;
}
boolean addLock = true;
// Checking if there is already a shared lock on this path
locksList = collectionLocks.elements();
while (locksList.hasMoreElements()) {
LockInfo currentLock = (LockInfo) locksList.nextElement();
if (currentLock.path.equals(lock.path)) {
if (currentLock.isExclusive()) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
} else {
if (lock.isExclusive()) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
}
currentLock.tokens.addElement(lockToken);
lock = currentLock;
addLock = false;
}
}
if (addLock) {
lock.tokens.addElement(lockToken);
collectionLocks.addElement(lock);
}
} else {
// Locking a single resource
// Retrieving an already existing lock on that resource
LockInfo presentLock = (LockInfo) resourceLocks.get(lock.path);
if (presentLock != null) {
if ((presentLock.isExclusive()) || (lock.isExclusive())) {
// If either lock is exclusive, the lock can't be
// granted
resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
return;
} else {
presentLock.tokens.addElement(lockToken);
lock = presentLock;
}
} else {
lock.tokens.addElement(lockToken);
resourceLocks.put(lock.path, lock);
// Checking if a resource exists at this path
exists = true;
try {
object = resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
if (!exists) {
// "Creating" a lock-null resource
int slash = lock.path.lastIndexOf('/");
String parentPath = lock.path.substring(0, slash);
Vector<String> lockNulls =
lockNullResources.get(parentPath);
if (lockNulls == null) {
lockNulls = new Vector<String>();
lockNullResources.put(parentPath, lockNulls);
}
lockNulls.addElement(lock.path);
}
// Add the Lock-Token header as by RFC 2518 8.10.1
// - only do this for newly created locks
resp.addHeader("Lock-Token", "<opaquelocktoken:"
+ lockToken + ">");
}
}
}
if (lockRequestType == LOCK_REFRESH) {
String ifHeader = req.getHeader("If");
if (ifHeader == null)
ifHeader = "";
// Checking resource locks
LockInfo toRenew = (LockInfo) resourceLocks.get(path);
Enumeration tokenList = null;
if (lock != null) {
// At least one of the tokens of the locks must have been given
tokenList = toRenew.tokens.elements();
while (tokenList.hasMoreElements()) {
String token = (String) tokenList.nextElement();
if (ifHeader.indexOf(token) != -1) {
toRenew.expiresAt = lock.expiresAt;
lock = toRenew;
}
}
}
// Checking inheritable collection locks
Enumeration collectionLocksList = collectionLocks.elements();
while (collectionLocksList.hasMoreElements()) {
toRenew = (LockInfo) collectionLocksList.nextElement();
if (path.equals(toRenew.path)) {
tokenList = toRenew.tokens.elements();
while (tokenList.hasMoreElements()) {
String token = (String) tokenList.nextElement();
if (ifHeader.indexOf(token) != -1) {
toRenew.expiresAt = lock.expiresAt;
lock = toRenew;
}
}
}
}
}
// Set the status, then generate the XML response containing
// the lock information
XMLWriter generatedXML = new XMLWriter();
generatedXML.writeXMLHeader();
generatedXML.writeElement(null, "prop"
+ generateNamespaceDeclarations(),
XMLWriter.OPENING);
generatedXML.writeElement(null, "lockdiscovery",
XMLWriter.OPENING);
lock.toXML(generatedXML);
generatedXML.writeElement(null, "lockdiscovery",
XMLWriter.CLOSING);
generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
resp.setStatus(WebdavStatus.SC_OK);
resp.setContentType("text/xml; charset=UTF-8");
Writer writer = resp.getWriter();
writer.write(generatedXML.toString());
writer.close();
| protected void | doMkcol(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)MKCOL Method.
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
String path = getRelativePath(req);
if ((path.toUpperCase().startsWith("/WEB-INF")) ||
(path.toUpperCase().startsWith("/META-INF"))) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
boolean exists = true;
Object object = null;
try {
object = resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
// Can't create a collection if a resource already exists at the given
// path
if (exists) {
// Get allowed methods
StringBuffer methodsAllowed = determineMethodsAllowed(resources,
req);
resp.addHeader("Allow", methodsAllowed.toString());
resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED);
return;
}
if (req.getInputStream().available() > 0) {
DocumentBuilder documentBuilder = getDocumentBuilder();
try {
Document document = documentBuilder.parse
(new InputSource(req.getInputStream()));
// TODO : Process this request body
resp.sendError(WebdavStatus.SC_NOT_IMPLEMENTED);
return;
} catch(SAXException saxe) {
// Parse error - assume invalid content
resp.sendError(WebdavStatus.SC_BAD_REQUEST);
return;
}
}
boolean result = true;
try {
resources.createSubcontext(path);
} catch (NamingException e) {
result = false;
}
if (!result) {
resp.sendError(WebdavStatus.SC_CONFLICT,
WebdavStatus.getStatusText
(WebdavStatus.SC_CONFLICT));
} else {
resp.setStatus(WebdavStatus.SC_CREATED);
// Removing any lock-null resource which would be present
lockNullResources.remove(path);
}
| protected void | doMove(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)MOVE Method.
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
String path = getRelativePath(req);
if (copyResource(req, resp)) {
deleteResource(path, req, resp, false);
}
| protected void | doOptions(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)OPTIONS Method.
resp.addHeader("DAV", "1,2");
StringBuffer methodsAllowed = determineMethodsAllowed(resources,
req);
resp.addHeader("Allow", methodsAllowed.toString());
resp.addHeader("MS-Author-Via", "DAV");
| protected void | doPropfind(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)PROPFIND Method.
if (!listings) {
// Get allowed methods
StringBuffer methodsAllowed = determineMethodsAllowed(resources,
req);
resp.addHeader("Allow", methodsAllowed.toString());
resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED);
return;
}
String path = getRelativePath(req);
if (path.endsWith("/"))
path = path.substring(0, path.length() - 1);
if ((path.toUpperCase().startsWith("/WEB-INF")) ||
(path.toUpperCase().startsWith("/META-INF"))) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
// Properties which are to be displayed.
Vector<String> properties = null;
// Propfind depth
int depth = INFINITY;
// Propfind type
int type = FIND_ALL_PROP;
String depthStr = req.getHeader("Depth");
if (depthStr == null) {
depth = INFINITY;
} else {
if (depthStr.equals("0")) {
depth = 0;
} else if (depthStr.equals("1")) {
depth = 1;
} else if (depthStr.equals("infinity")) {
depth = INFINITY;
}
}
Node propNode = null;
DocumentBuilder documentBuilder = getDocumentBuilder();
try {
Document document = documentBuilder.parse
(new InputSource(req.getInputStream()));
// Get the root element of the document
Element rootElement = document.getDocumentElement();
NodeList childList = rootElement.getChildNodes();
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
if (currentNode.getNodeName().endsWith("prop")) {
type = FIND_BY_PROPERTY;
propNode = currentNode;
}
if (currentNode.getNodeName().endsWith("propname")) {
type = FIND_PROPERTY_NAMES;
}
if (currentNode.getNodeName().endsWith("allprop")) {
type = FIND_ALL_PROP;
}
break;
}
}
} catch (SAXException e) {
// Most likely there was no content : we use the defaults.
} catch (IOException e) {
// Most likely there was no content : we use the defaults.
}
if (type == FIND_BY_PROPERTY) {
properties = new Vector<String>();
NodeList childList = propNode.getChildNodes();
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
String nodeName = currentNode.getNodeName();
String propertyName = null;
if (nodeName.indexOf(':") != -1) {
propertyName = nodeName.substring
(nodeName.indexOf(':") + 1);
} else {
propertyName = nodeName;
}
// href is a live property which is handled differently
properties.addElement(propertyName);
break;
}
}
}
boolean exists = true;
Object object = null;
try {
object = resources.lookup(path);
} catch (NamingException e) {
exists = false;
int slash = path.lastIndexOf('/");
if (slash != -1) {
String parentPath = path.substring(0, slash);
Vector currentLockNullResources =
(Vector) lockNullResources.get(parentPath);
if (currentLockNullResources != null) {
Enumeration lockNullResourcesList =
currentLockNullResources.elements();
while (lockNullResourcesList.hasMoreElements()) {
String lockNullPath = (String)
lockNullResourcesList.nextElement();
if (lockNullPath.equals(path)) {
resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
resp.setContentType("text/xml; charset=UTF-8");
// Create multistatus object
XMLWriter generatedXML =
new XMLWriter(resp.getWriter());
generatedXML.writeXMLHeader();
generatedXML.writeElement
(null, "multistatus"
+ generateNamespaceDeclarations(),
XMLWriter.OPENING);
parseLockNullProperties
(req, generatedXML, lockNullPath, type,
properties);
generatedXML.writeElement(null, "multistatus",
XMLWriter.CLOSING);
generatedXML.sendData();
return;
}
}
}
}
}
if (!exists) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
return;
}
resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
resp.setContentType("text/xml; charset=UTF-8");
// Create multistatus object
XMLWriter generatedXML = new XMLWriter(resp.getWriter());
generatedXML.writeXMLHeader();
generatedXML.writeElement(null, "multistatus"
+ generateNamespaceDeclarations(),
XMLWriter.OPENING);
if (depth == 0) {
parseProperties(req, generatedXML, path, type,
properties);
} else {
// The stack always contains the object of the current level
Stack<String> stack = new Stack<String>();
stack.push(path);
// Stack of the objects one level below
Stack<String> stackBelow = new Stack<String>();
while ((!stack.isEmpty()) && (depth >= 0)) {
String currentPath = (String) stack.pop();
parseProperties(req, generatedXML, currentPath,
type, properties);
try {
object = resources.lookup(currentPath);
} catch (NamingException e) {
continue;
}
if ((object instanceof DirContext) && (depth > 0)) {
try {
NamingEnumeration enumeration = resources.list(currentPath);
while (enumeration.hasMoreElements()) {
NameClassPair ncPair =
(NameClassPair) enumeration.nextElement();
String newPath = currentPath;
if (!(newPath.endsWith("/")))
newPath += "/";
newPath += ncPair.getName();
stackBelow.push(newPath);
}
} catch (NamingException e) {
resp.sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
path);
return;
}
// Displaying the lock-null resources present in that
// collection
String lockPath = currentPath;
if (lockPath.endsWith("/"))
lockPath =
lockPath.substring(0, lockPath.length() - 1);
Vector currentLockNullResources =
(Vector) lockNullResources.get(lockPath);
if (currentLockNullResources != null) {
Enumeration lockNullResourcesList =
currentLockNullResources.elements();
while (lockNullResourcesList.hasMoreElements()) {
String lockNullPath = (String)
lockNullResourcesList.nextElement();
parseLockNullProperties
(req, generatedXML, lockNullPath, type,
properties);
}
}
}
if (stack.isEmpty()) {
depth--;
stack = stackBelow;
stackBelow = new Stack<String>();
}
generatedXML.sendData();
}
}
generatedXML.writeElement(null, "multistatus",
XMLWriter.CLOSING);
generatedXML.sendData();
| protected void | doProppatch(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)PROPPATCH Method.
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
| protected void | doPut(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)Process a POST request for the specified resource.
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
super.doPut(req, resp);
String path = getRelativePath(req);
// Removing any lock-null resource which would be present
lockNullResources.remove(path);
| protected void | doUnlock(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)UNLOCK Method.
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
String path = getRelativePath(req);
String lockTokenHeader = req.getHeader("Lock-Token");
if (lockTokenHeader == null)
lockTokenHeader = "";
// Checking resource locks
LockInfo lock = (LockInfo) resourceLocks.get(path);
Enumeration tokenList = null;
if (lock != null) {
// At least one of the tokens of the locks must have been given
tokenList = lock.tokens.elements();
while (tokenList.hasMoreElements()) {
String token = (String) tokenList.nextElement();
if (lockTokenHeader.indexOf(token) != -1) {
lock.tokens.removeElement(token);
}
}
if (lock.tokens.isEmpty()) {
resourceLocks.remove(path);
// Removing any lock-null resource which would be present
lockNullResources.remove(path);
}
}
// Checking inheritable collection locks
Enumeration collectionLocksList = collectionLocks.elements();
while (collectionLocksList.hasMoreElements()) {
lock = (LockInfo) collectionLocksList.nextElement();
if (path.equals(lock.path)) {
tokenList = lock.tokens.elements();
while (tokenList.hasMoreElements()) {
String token = (String) tokenList.nextElement();
if (lockTokenHeader.indexOf(token) != -1) {
lock.tokens.removeElement(token);
break;
}
}
if (lock.tokens.isEmpty()) {
collectionLocks.removeElement(lock);
// Removing any lock-null resource which would be present
lockNullResources.remove(path);
}
}
}
resp.setStatus(WebdavStatus.SC_NO_CONTENT);
| private boolean | generateLockDiscovery(java.lang.String path, org.apache.catalina.util.XMLWriter generatedXML)Print the lock discovery information associated with a path.
LockInfo resourceLock = (LockInfo) resourceLocks.get(path);
Enumeration collectionLocksList = collectionLocks.elements();
boolean wroteStart = false;
if (resourceLock != null) {
wroteStart = true;
generatedXML.writeElement(null, "lockdiscovery",
XMLWriter.OPENING);
resourceLock.toXML(generatedXML);
}
while (collectionLocksList.hasMoreElements()) {
LockInfo currentLock =
(LockInfo) collectionLocksList.nextElement();
if (path.startsWith(currentLock.path)) {
if (!wroteStart) {
wroteStart = true;
generatedXML.writeElement(null, "lockdiscovery",
XMLWriter.OPENING);
}
currentLock.toXML(generatedXML);
}
}
if (wroteStart) {
generatedXML.writeElement(null, "lockdiscovery",
XMLWriter.CLOSING);
} else {
return false;
}
return true;
| private java.lang.String | generateNamespaceDeclarations()Generate the namespace declarations.
return " xmlns=\"" + DEFAULT_NAMESPACE + "\"";
| protected javax.xml.parsers.DocumentBuilder | getDocumentBuilder()Return JAXP document builder instance.
DocumentBuilder documentBuilder = null;
DocumentBuilderFactory documentBuilderFactory = null;
try {
documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
documentBuilder = documentBuilderFactory.newDocumentBuilder();
} catch(ParserConfigurationException e) {
throw new ServletException
(sm.getString("webdavservlet.jaxpfailed"));
}
return documentBuilder;
| private java.lang.String | getISOCreationDate(long creationDate)Get creation date in ISO format.
StringBuffer creationDateValue = new StringBuffer
(creationDateFormat.format
(new Date(creationDate)));
/*
int offset = Calendar.getInstance().getTimeZone().getRawOffset()
/ 3600000; // FIXME ?
if (offset < 0) {
creationDateValue.append("-");
offset = -offset;
} else if (offset > 0) {
creationDateValue.append("+");
}
if (offset != 0) {
if (offset < 10)
creationDateValue.append("0");
creationDateValue.append(offset + ":00");
} else {
creationDateValue.append("Z");
}
*/
return creationDateValue.toString();
| public void | init()Initialize this servlet.
// --------------------------------------------------------- Public Methods
super.init();
if (getServletConfig().getInitParameter("secret") != null)
secret = getServletConfig().getInitParameter("secret");
// Load the MD5 helper used to calculate signatures.
try {
md5Helper = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new UnavailableException("No MD5");
}
| private boolean | isLocked(javax.servlet.http.HttpServletRequest req)Check to see if a resource is currently write locked. The method
will look at the "If" header to make sure the client
has give the appropriate lock tokens.
String path = getRelativePath(req);
String ifHeader = req.getHeader("If");
if (ifHeader == null)
ifHeader = "";
String lockTokenHeader = req.getHeader("Lock-Token");
if (lockTokenHeader == null)
lockTokenHeader = "";
return isLocked(path, ifHeader + lockTokenHeader);
| private boolean | isLocked(java.lang.String path, java.lang.String ifHeader)Check to see if a resource is currently write locked.
// Checking resource locks
LockInfo lock = (LockInfo) resourceLocks.get(path);
Enumeration tokenList = null;
if ((lock != null) && (lock.hasExpired())) {
resourceLocks.remove(path);
} else if (lock != null) {
// At least one of the tokens of the locks must have been given
tokenList = lock.tokens.elements();
boolean tokenMatch = false;
while (tokenList.hasMoreElements()) {
String token = (String) tokenList.nextElement();
if (ifHeader.indexOf(token) != -1)
tokenMatch = true;
}
if (!tokenMatch)
return true;
}
// Checking inheritable collection locks
Enumeration collectionLocksList = collectionLocks.elements();
while (collectionLocksList.hasMoreElements()) {
lock = (LockInfo) collectionLocksList.nextElement();
if (lock.hasExpired()) {
collectionLocks.removeElement(lock);
} else if (path.startsWith(lock.path)) {
tokenList = lock.tokens.elements();
boolean tokenMatch = false;
while (tokenList.hasMoreElements()) {
String token = (String) tokenList.nextElement();
if (ifHeader.indexOf(token) != -1)
tokenMatch = true;
}
if (!tokenMatch)
return true;
}
}
return false;
| protected java.lang.String | normalize(java.lang.String path)Return a context-relative path, beginning with a "/", that represents
the canonical version of the specified path after ".." and "." elements
are resolved out. If the specified path attempts to go outside the
boundaries of the current context (i.e. too many ".." path elements
are present), return null instead.
if (path == null)
return null;
// Create a place for the normalized path
String normalized = path;
if (normalized == null)
return (null);
if (normalized.equals("/."))
return "/";
// Normalize the slashes and add leading slash if necessary
if (normalized.indexOf('\\") >= 0)
normalized = normalized.replace('\\", '/");
if (!normalized.startsWith("/"))
normalized = "/" + normalized;
// Resolve occurrences of "//" in the normalized path
while (true) {
int index = normalized.indexOf("//");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 1);
}
// Resolve occurrences of "/./" in the normalized path
while (true) {
int index = normalized.indexOf("/./");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 2);
}
// Resolve occurrences of "/../" in the normalized path
while (true) {
int index = normalized.indexOf("/../");
if (index < 0)
break;
if (index == 0)
return (null); // Trying to go outside our context
int index2 = normalized.lastIndexOf('/", index - 1);
normalized = normalized.substring(0, index2) +
normalized.substring(index + 3);
}
// Return the normalized path that we have completed
return (normalized);
| private void | parseLockNullProperties(javax.servlet.http.HttpServletRequest req, org.apache.catalina.util.XMLWriter generatedXML, java.lang.String path, int type, java.util.Vector propertiesVector)Propfind helper method. Dispays the properties of a lock-null resource.
// Exclude any resource in the /WEB-INF and /META-INF subdirectories
// (the "toUpperCase()" avoids problems on Windows systems)
if (path.toUpperCase().startsWith("/WEB-INF") ||
path.toUpperCase().startsWith("/META-INF"))
return;
// Retrieving the lock associated with the lock-null resource
LockInfo lock = (LockInfo) resourceLocks.get(path);
if (lock == null)
return;
generatedXML.writeElement(null, "response", XMLWriter.OPENING);
String status = new String("HTTP/1.1 " + WebdavStatus.SC_OK + " "
+ WebdavStatus.getStatusText
(WebdavStatus.SC_OK));
// Generating href element
generatedXML.writeElement(null, "href", XMLWriter.OPENING);
String absoluteUri = req.getRequestURI();
String relativePath = getRelativePath(req);
String toAppend = path.substring(relativePath.length());
if (!toAppend.startsWith("/"))
toAppend = "/" + toAppend;
generatedXML.writeText(rewriteUrl(normalize(absoluteUri + toAppend)));
generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
String resourceName = path;
int lastSlash = path.lastIndexOf('/");
if (lastSlash != -1)
resourceName = resourceName.substring(lastSlash + 1);
switch (type) {
case FIND_ALL_PROP :
generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
generatedXML.writeProperty
(null, "creationdate",
getISOCreationDate(lock.creationDate.getTime()));
generatedXML.writeElement
(null, "displayname", XMLWriter.OPENING);
generatedXML.writeData(resourceName);
generatedXML.writeElement
(null, "displayname", XMLWriter.CLOSING);
generatedXML.writeProperty(null, "getlastmodified",
FastHttpDateFormat.formatDate
(lock.creationDate.getTime(), null));
generatedXML.writeProperty
(null, "getcontentlength", String.valueOf(0));
generatedXML.writeProperty(null, "getcontenttype", "");
generatedXML.writeProperty(null, "getetag", "");
generatedXML.writeElement(null, "resourcetype",
XMLWriter.OPENING);
generatedXML.writeElement(null, "lock-null", XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "resourcetype",
XMLWriter.CLOSING);
generatedXML.writeProperty(null, "source", "");
String supportedLocks = "<lockentry>"
+ "<lockscope><exclusive/></lockscope>"
+ "<locktype><write/></locktype>"
+ "</lockentry>" + "<lockentry>"
+ "<lockscope><shared/></lockscope>"
+ "<locktype><write/></locktype>"
+ "</lockentry>";
generatedXML.writeElement(null, "supportedlock",
XMLWriter.OPENING);
generatedXML.writeText(supportedLocks);
generatedXML.writeElement(null, "supportedlock",
XMLWriter.CLOSING);
generateLockDiscovery(path, generatedXML);
generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
generatedXML.writeElement(null, "status", XMLWriter.OPENING);
generatedXML.writeText(status);
generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
break;
case FIND_PROPERTY_NAMES :
generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
generatedXML.writeElement(null, "creationdate",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "displayname",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "getcontentlanguage",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "getcontentlength",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "getcontenttype",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "getetag",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "getlastmodified",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "resourcetype",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "source",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "lockdiscovery",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
generatedXML.writeElement(null, "status", XMLWriter.OPENING);
generatedXML.writeText(status);
generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
break;
case FIND_BY_PROPERTY :
Vector<String> propertiesNotFound = new Vector<String>();
// Parse the list of properties
generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
Enumeration properties = propertiesVector.elements();
while (properties.hasMoreElements()) {
String property = (String) properties.nextElement();
if (property.equals("creationdate")) {
generatedXML.writeProperty
(null, "creationdate",
getISOCreationDate(lock.creationDate.getTime()));
} else if (property.equals("displayname")) {
generatedXML.writeElement
(null, "displayname", XMLWriter.OPENING);
generatedXML.writeData(resourceName);
generatedXML.writeElement
(null, "displayname", XMLWriter.CLOSING);
} else if (property.equals("getcontentlanguage")) {
generatedXML.writeElement(null, "getcontentlanguage",
XMLWriter.NO_CONTENT);
} else if (property.equals("getcontentlength")) {
generatedXML.writeProperty
(null, "getcontentlength", (String.valueOf(0)));
} else if (property.equals("getcontenttype")) {
generatedXML.writeProperty
(null, "getcontenttype", "");
} else if (property.equals("getetag")) {
generatedXML.writeProperty(null, "getetag", "");
} else if (property.equals("getlastmodified")) {
generatedXML.writeProperty
(null, "getlastmodified",
FastHttpDateFormat.formatDate
(lock.creationDate.getTime(), null));
} else if (property.equals("resourcetype")) {
generatedXML.writeElement(null, "resourcetype",
XMLWriter.OPENING);
generatedXML.writeElement(null, "lock-null",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "resourcetype",
XMLWriter.CLOSING);
} else if (property.equals("source")) {
generatedXML.writeProperty(null, "source", "");
} else if (property.equals("supportedlock")) {
supportedLocks = "<lockentry>"
+ "<lockscope><exclusive/></lockscope>"
+ "<locktype><write/></locktype>"
+ "</lockentry>" + "<lockentry>"
+ "<lockscope><shared/></lockscope>"
+ "<locktype><write/></locktype>"
+ "</lockentry>";
generatedXML.writeElement(null, "supportedlock",
XMLWriter.OPENING);
generatedXML.writeText(supportedLocks);
generatedXML.writeElement(null, "supportedlock",
XMLWriter.CLOSING);
} else if (property.equals("lockdiscovery")) {
if (!generateLockDiscovery(path, generatedXML))
propertiesNotFound.addElement(property);
} else {
propertiesNotFound.addElement(property);
}
}
generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
generatedXML.writeElement(null, "status", XMLWriter.OPENING);
generatedXML.writeText(status);
generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
Enumeration propertiesNotFoundList = propertiesNotFound.elements();
if (propertiesNotFoundList.hasMoreElements()) {
status = new String("HTTP/1.1 " + WebdavStatus.SC_NOT_FOUND
+ " " + WebdavStatus.getStatusText
(WebdavStatus.SC_NOT_FOUND));
generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
while (propertiesNotFoundList.hasMoreElements()) {
generatedXML.writeElement
(null, (String) propertiesNotFoundList.nextElement(),
XMLWriter.NO_CONTENT);
}
generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
generatedXML.writeElement(null, "status", XMLWriter.OPENING);
generatedXML.writeText(status);
generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
}
break;
}
generatedXML.writeElement(null, "response", XMLWriter.CLOSING);
| private void | parseProperties(javax.servlet.http.HttpServletRequest req, org.apache.catalina.util.XMLWriter generatedXML, java.lang.String path, int type, java.util.Vector propertiesVector)Propfind helper method.
// Exclude any resource in the /WEB-INF and /META-INF subdirectories
// (the "toUpperCase()" avoids problems on Windows systems)
if (path.toUpperCase().startsWith("/WEB-INF") ||
path.toUpperCase().startsWith("/META-INF"))
return;
CacheEntry cacheEntry = resources.lookupCache(path);
generatedXML.writeElement(null, "response", XMLWriter.OPENING);
String status = new String("HTTP/1.1 " + WebdavStatus.SC_OK + " "
+ WebdavStatus.getStatusText
(WebdavStatus.SC_OK));
// Generating href element
generatedXML.writeElement(null, "href", XMLWriter.OPENING);
String href = req.getContextPath() + req.getServletPath();
if ((href.endsWith("/")) && (path.startsWith("/")))
href += path.substring(1);
else
href += path;
if ((cacheEntry.context != null) && (!href.endsWith("/")))
href += "/";
generatedXML.writeText(rewriteUrl(href));
generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
String resourceName = path;
int lastSlash = path.lastIndexOf('/");
if (lastSlash != -1)
resourceName = resourceName.substring(lastSlash + 1);
switch (type) {
case FIND_ALL_PROP :
generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
generatedXML.writeProperty
(null, "creationdate",
getISOCreationDate(cacheEntry.attributes.getCreation()));
generatedXML.writeElement(null, "displayname", XMLWriter.OPENING);
generatedXML.writeData(resourceName);
generatedXML.writeElement(null, "displayname", XMLWriter.CLOSING);
if (cacheEntry.resource != null) {
generatedXML.writeProperty
(null, "getlastmodified", FastHttpDateFormat.formatDate
(cacheEntry.attributes.getLastModified(), null));
generatedXML.writeProperty
(null, "getcontentlength",
String.valueOf(cacheEntry.attributes.getContentLength()));
String contentType = getServletContext().getMimeType
(cacheEntry.name);
if (contentType != null) {
generatedXML.writeProperty(null, "getcontenttype",
contentType);
}
generatedXML.writeProperty(null, "getetag",
getETag(cacheEntry.attributes));
generatedXML.writeElement(null, "resourcetype",
XMLWriter.NO_CONTENT);
} else {
generatedXML.writeElement(null, "resourcetype",
XMLWriter.OPENING);
generatedXML.writeElement(null, "collection",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "resourcetype",
XMLWriter.CLOSING);
}
generatedXML.writeProperty(null, "source", "");
String supportedLocks = "<lockentry>"
+ "<lockscope><exclusive/></lockscope>"
+ "<locktype><write/></locktype>"
+ "</lockentry>" + "<lockentry>"
+ "<lockscope><shared/></lockscope>"
+ "<locktype><write/></locktype>"
+ "</lockentry>";
generatedXML.writeElement(null, "supportedlock",
XMLWriter.OPENING);
generatedXML.writeText(supportedLocks);
generatedXML.writeElement(null, "supportedlock",
XMLWriter.CLOSING);
generateLockDiscovery(path, generatedXML);
generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
generatedXML.writeElement(null, "status", XMLWriter.OPENING);
generatedXML.writeText(status);
generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
break;
case FIND_PROPERTY_NAMES :
generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
generatedXML.writeElement(null, "creationdate",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "displayname",
XMLWriter.NO_CONTENT);
if (cacheEntry.resource != null) {
generatedXML.writeElement(null, "getcontentlanguage",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "getcontentlength",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "getcontenttype",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "getetag",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "getlastmodified",
XMLWriter.NO_CONTENT);
}
generatedXML.writeElement(null, "resourcetype",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "source", XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "lockdiscovery",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
generatedXML.writeElement(null, "status", XMLWriter.OPENING);
generatedXML.writeText(status);
generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
break;
case FIND_BY_PROPERTY :
Vector<String> propertiesNotFound = new Vector<String>();
// Parse the list of properties
generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
Enumeration<String> properties = propertiesVector.elements();
while (properties.hasMoreElements()) {
String property = (String) properties.nextElement();
if (property.equals("creationdate")) {
generatedXML.writeProperty
(null, "creationdate",
getISOCreationDate(cacheEntry.attributes.getCreation()));
} else if (property.equals("displayname")) {
generatedXML.writeElement
(null, "displayname", XMLWriter.OPENING);
generatedXML.writeData(resourceName);
generatedXML.writeElement
(null, "displayname", XMLWriter.CLOSING);
} else if (property.equals("getcontentlanguage")) {
if (cacheEntry.context != null) {
propertiesNotFound.addElement(property);
} else {
generatedXML.writeElement(null, "getcontentlanguage",
XMLWriter.NO_CONTENT);
}
} else if (property.equals("getcontentlength")) {
if (cacheEntry.context != null) {
propertiesNotFound.addElement(property);
} else {
generatedXML.writeProperty
(null, "getcontentlength",
(String.valueOf(cacheEntry.attributes.getContentLength())));
}
} else if (property.equals("getcontenttype")) {
if (cacheEntry.context != null) {
propertiesNotFound.addElement(property);
} else {
generatedXML.writeProperty
(null, "getcontenttype",
getServletContext().getMimeType
(cacheEntry.name));
}
} else if (property.equals("getetag")) {
if (cacheEntry.context != null) {
propertiesNotFound.addElement(property);
} else {
generatedXML.writeProperty
(null, "getetag", getETag(cacheEntry.attributes));
}
} else if (property.equals("getlastmodified")) {
if (cacheEntry.context != null) {
propertiesNotFound.addElement(property);
} else {
generatedXML.writeProperty
(null, "getlastmodified", FastHttpDateFormat.formatDate
(cacheEntry.attributes.getLastModified(), null));
}
} else if (property.equals("resourcetype")) {
if (cacheEntry.context != null) {
generatedXML.writeElement(null, "resourcetype",
XMLWriter.OPENING);
generatedXML.writeElement(null, "collection",
XMLWriter.NO_CONTENT);
generatedXML.writeElement(null, "resourcetype",
XMLWriter.CLOSING);
} else {
generatedXML.writeElement(null, "resourcetype",
XMLWriter.NO_CONTENT);
}
} else if (property.equals("source")) {
generatedXML.writeProperty(null, "source", "");
} else if (property.equals("supportedlock")) {
supportedLocks = "<lockentry>"
+ "<lockscope><exclusive/></lockscope>"
+ "<locktype><write/></locktype>"
+ "</lockentry>" + "<lockentry>"
+ "<lockscope><shared/></lockscope>"
+ "<locktype><write/></locktype>"
+ "</lockentry>";
generatedXML.writeElement(null, "supportedlock",
XMLWriter.OPENING);
generatedXML.writeText(supportedLocks);
generatedXML.writeElement(null, "supportedlock",
XMLWriter.CLOSING);
} else if (property.equals("lockdiscovery")) {
if (!generateLockDiscovery(path, generatedXML))
propertiesNotFound.addElement(property);
} else {
propertiesNotFound.addElement(property);
}
}
generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
generatedXML.writeElement(null, "status", XMLWriter.OPENING);
generatedXML.writeText(status);
generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
Enumeration propertiesNotFoundList = propertiesNotFound.elements();
if (propertiesNotFoundList.hasMoreElements()) {
status = new String("HTTP/1.1 " + WebdavStatus.SC_NOT_FOUND
+ " " + WebdavStatus.getStatusText
(WebdavStatus.SC_NOT_FOUND));
generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
while (propertiesNotFoundList.hasMoreElements()) {
generatedXML.writeElement
(null, (String) propertiesNotFoundList.nextElement(),
XMLWriter.NO_CONTENT);
}
generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
generatedXML.writeElement(null, "status", XMLWriter.OPENING);
generatedXML.writeText(status);
generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
}
break;
}
generatedXML.writeElement(null, "response", XMLWriter.CLOSING);
| private void | sendReport(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp, java.util.Hashtable errorList)Send a multistatus element containing a complete error report to the
client.
resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
String absoluteUri = req.getRequestURI();
String relativePath = getRelativePath(req);
XMLWriter generatedXML = new XMLWriter();
generatedXML.writeXMLHeader();
generatedXML.writeElement(null, "multistatus"
+ generateNamespaceDeclarations(),
XMLWriter.OPENING);
Enumeration pathList = errorList.keys();
while (pathList.hasMoreElements()) {
String errorPath = (String) pathList.nextElement();
int errorCode = ((Integer) errorList.get(errorPath)).intValue();
generatedXML.writeElement(null, "response", XMLWriter.OPENING);
generatedXML.writeElement(null, "href", XMLWriter.OPENING);
String toAppend = errorPath.substring(relativePath.length());
if (!toAppend.startsWith("/"))
toAppend = "/" + toAppend;
generatedXML.writeText(absoluteUri + toAppend);
generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
generatedXML.writeElement(null, "status", XMLWriter.OPENING);
generatedXML
.writeText("HTTP/1.1 " + errorCode + " "
+ WebdavStatus.getStatusText(errorCode));
generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
generatedXML.writeElement(null, "response", XMLWriter.CLOSING);
}
generatedXML.writeElement(null, "multistatus", XMLWriter.CLOSING);
Writer writer = resp.getWriter();
writer.write(generatedXML.toString());
writer.close();
| protected void | service(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)Handles the special WebDAV methods.
String method = req.getMethod();
if (debug > 0) {
String path = getRelativePath(req);
log("[" + method + "] " + path);
}
if (method.equals(METHOD_PROPFIND)) {
doPropfind(req, resp);
} else if (method.equals(METHOD_PROPPATCH)) {
doProppatch(req, resp);
} else if (method.equals(METHOD_MKCOL)) {
doMkcol(req, resp);
} else if (method.equals(METHOD_COPY)) {
doCopy(req, resp);
} else if (method.equals(METHOD_MOVE)) {
doMove(req, resp);
} else if (method.equals(METHOD_LOCK)) {
doLock(req, resp);
} else if (method.equals(METHOD_UNLOCK)) {
doUnlock(req, resp);
} else {
// DefaultServlet processing
super.service(req, resp);
}
|
|