You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2001/01/23 05:47:58 UTC
cvs commit: jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets DefaultServlet.java LocalStrings.properties WebdavServlet.java
remm 01/01/22 20:47:57
Modified: catalina/src/share/org/apache/catalina/servlets
DefaultServlet.java LocalStrings.properties
WebdavServlet.java
Log:
- Backport from 4.1.
- Update DefaultServlet and WebdavServlet to use the directory contexts.
Revision Changes Path
1.20 +436 -69 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/DefaultServlet.java
Index: DefaultServlet.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/DefaultServlet.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- DefaultServlet.java 2001/01/18 20:20:55 1.19
+++ DefaultServlet.java 2001/01/23 04:47:57 1.20
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/DefaultServlet.java,v 1.19 2001/01/18 20:20:55 remm Exp $
- * $Revision: 1.19 $
- * $Date: 2001/01/18 20:20:55 $
+ * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/DefaultServlet.java,v 1.20 2001/01/23 04:47:57 remm Exp $
+ * $Revision: 1.20 $
+ * $Date: 2001/01/23 04:47:57 $
*
* ====================================================================
*
@@ -66,6 +66,8 @@
import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
@@ -76,6 +78,7 @@
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
+import java.net.URLEncoder;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Enumeration;
@@ -95,16 +98,19 @@
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.naming.NamingException;
+import javax.naming.InitialContext;
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NameClassPair;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import org.apache.naming.resources.Resource;
+import org.apache.naming.resources.ResourceAttributes;
import org.apache.catalina.Globals;
-import org.apache.catalina.Resources;
-import org.apache.catalina.core.ApplicationContext;
-import org.apache.catalina.resources.ResourceBean;
-import org.apache.catalina.resources.DirectoryBean;
import org.apache.catalina.util.MD5Encoder;
import org.apache.catalina.util.StringManager;
-import org.apache.catalina.util.xml.SaxContext;
-import org.apache.catalina.util.xml.XmlAction;
-import org.apache.catalina.util.xml.XmlMapper;
/**
@@ -113,7 +119,7 @@
*
* @author Craig R. McClanahan
* @author Remy Maucherat
- * @version $Revision: 1.19 $ $Date: 2001/01/18 20:20:55 $
+ * @version $Revision: 1.20 $ $Date: 2001/01/23 04:47:57 $
*/
public class DefaultServlet
@@ -201,6 +207,12 @@
/**
+ * JNDI resources name.
+ */
+ protected static final String RESOURCES_JNDI_NAME = "java:/comp/Resources";
+
+
+ /**
* The string manager for this package.
*/
protected static StringManager sm =
@@ -295,6 +307,38 @@
/**
+ * Get resources. This method will try to retrieve the resources through
+ * JNDI first, then in the servlet context if JNDI has failed (it could be
+ * disabled). It will return null.
+ *
+ * @return A JNDI DirContext, or null.
+ */
+ protected DirContext getResources() {
+
+ // First : try JNDI
+ try {
+ return
+ (DirContext) new InitialContext().lookup(RESOURCES_JNDI_NAME);
+ } catch (NamingException e) {
+ // Failed
+ } catch (ClassCastException e) {
+ // Failed : Not the right type
+ }
+
+ // If it has failed, try the servlet context
+ try {
+ return (DirContext) getServletContext()
+ .getAttribute(Globals.RESOURCES_ATTR);
+ } catch (ClassCastException e) {
+ // Failed : Not the right type
+ }
+
+ return null;
+
+ }
+
+
+ /**
* Show HTTP header information.
*/
protected void showRequestInfo(HttpServletRequest req) {
@@ -408,7 +452,7 @@
if ((result == null) || (result.equals(""))) {
result = "/";
}
- return result;
+ return normalize(result);
}
@@ -494,14 +538,30 @@
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
}
- // Retrieve the Catalina context
- ApplicationContext context = (ApplicationContext) getServletContext();
- Resources resources = context.getResources();
+ // Retrieve the resources
+ DirContext resources = getResources();
- boolean exists = resources.exists(path);
+ if (resources == null) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
+ }
- boolean result = resources.setResource(path, req.getInputStream());
+ boolean exists = true;
+ try {
+ resources.lookup(path);
+ } catch (NamingException e) {
+ exists = false;
+ }
+ boolean result = true;
+ try {
+ Resource newResource = new Resource(req.getInputStream());
+ // FIXME: Add attributes
+ resources.bind(path, newResource);
+ } catch(NamingException e) {
+ result = false;
+ }
+
if (result) {
if (exists) {
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
@@ -535,13 +595,28 @@
String path = getRelativePath(req);
// Retrieve the Catalina context
- ApplicationContext context = (ApplicationContext) getServletContext();
- Resources resources = context.getResources();
+ // Retrieve the resources
+ DirContext resources = getResources();
+
+ if (resources == null) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
+ }
- boolean exists = resources.exists(path);
+ boolean exists = true;
+ try {
+ resources.lookup(path);
+ } catch (NamingException e) {
+ exists = false;
+ }
if (exists) {
- boolean result = resources.deleteResource(path);
+ boolean result = true;
+ try {
+ resources.unbind(path);
+ } catch (NamingException e) {
+ result = false;
+ }
if (result) {
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
} else {
@@ -744,6 +819,9 @@
*/
protected String normalize(String path) {
+ if (path == null)
+ return null;
+
String normalized = path;
// Resolve encoded characters in the normalized path,
@@ -818,6 +896,29 @@
}
+ /**
+ * URL rewriter.
+ *
+ * @param path Path which has to be rewiten
+ */
+ protected String rewriteUrl(String path) {
+
+ String normalized = path;
+
+ // Replace " " with "%20"
+ while (true) {
+ int index = normalized.indexOf(" ");
+ if (index < 0)
+ break;
+ normalized = normalized.substring(0, index) + "%20"
+ + normalized.substring(index + 1);
+ }
+
+ return normalized;
+
+ }
+
+
// -------------------------------------------------------- Private Methods
@@ -837,8 +938,7 @@
IOException exception = null;
// FIXME : i18n ?
- InputStream resourceInputStream =
- resourceInfo.resources.getResourceAsStream(resourceInfo.path);
+ InputStream resourceInputStream = resourceInfo.getStream();
InputStream istream = new BufferedInputStream
(resourceInputStream, input);
@@ -874,8 +974,7 @@
IOException exception = null;
- InputStream resourceInputStream =
- resourceInfo.resources.getResourceAsStream(resourceInfo.path);
+ InputStream resourceInputStream = resourceInfo.getStream();
// FIXME : i18n ?
Reader reader = new InputStreamReader(resourceInputStream);
@@ -912,8 +1011,7 @@
IOException exception = null;
- InputStream resourceInputStream =
- resourceInfo.resources.getResourceAsStream(resourceInfo.path);
+ InputStream resourceInputStream = resourceInfo.getStream();
InputStream istream =
new BufferedInputStream(resourceInputStream, input);
exception = copyRange(istream, ostream, range.start, range.end);
@@ -948,8 +1046,7 @@
IOException exception = null;
- InputStream resourceInputStream =
- resourceInfo.resources.getResourceAsStream(resourceInfo.path);
+ InputStream resourceInputStream = resourceInfo.getStream();
Reader reader = new InputStreamReader(resourceInputStream);
exception = copyRange(reader, writer, range.start, range.end);
@@ -986,8 +1083,7 @@
while ( (exception == null) && (ranges.hasMoreElements()) ) {
- InputStream resourceInputStream =
- resourceInfo.resources.getResourceAsStream(resourceInfo.path);
+ InputStream resourceInputStream = resourceInfo.getStream();
InputStream istream = // FIXME: internationalization???????
new BufferedInputStream(resourceInputStream, input);
@@ -1042,8 +1138,7 @@
while ( (exception == null) && (ranges.hasMoreElements()) ) {
- InputStream resourceInputStream =
- resourceInfo.resources.getResourceAsStream(resourceInfo.path);
+ InputStream resourceInputStream = resourceInfo.getStream();
Reader reader = new InputStreamReader(resourceInputStream);
Range currentRange = (Range) ranges.nextElement();
@@ -1262,7 +1357,7 @@
* @param pathname Pathname of the file to be served
*/
private ResourceInfo checkWelcomeFiles(String pathname,
- Resources resources) {
+ DirContext resources) {
String collectionName = pathname;
if (!pathname.endsWith("/")) {
@@ -1323,17 +1418,15 @@
// Exclude any resource in the /WEB-INF and /META-INF subdirectories
// (the "toUpperCase()" avoids problems on Windows systems)
- String normalizedPath = normalize(path);
- if ((normalizedPath == null) ||
- normalizedPath.toUpperCase().startsWith("/WEB-INF") ||
- normalizedPath.toUpperCase().startsWith("/META-INF")) {
+ if ((path == null) ||
+ path.toUpperCase().startsWith("/WEB-INF") ||
+ path.toUpperCase().startsWith("/META-INF")) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, path);
return;
}
// Retrieve the Catalina context and Resources implementation
- ApplicationContext context = (ApplicationContext) getServletContext();
- Resources resources = context.getResources();
+ DirContext resources = getResources();
ResourceInfo resourceInfo = new ResourceInfo(path, resources);
if (!resourceInfo.exists) {
@@ -1366,18 +1459,12 @@
if ((contextPath != null) && (!contextPath.equals("/"))) {
redirectPath = contextPath + redirectPath;
}
- response.sendRedirect(redirectPath);
+ response.sendRedirect(rewriteUrl(redirectPath));
return;
}
}
- if (!resourceInfo.exists()) {
- response.sendError(HttpServletResponse.SC_NOT_FOUND,
- resourceInfo.path);
- return;
- }
-
// Checking If headers
if ( !checkIfHeaders(request, response, resourceInfo) ) {
return;
@@ -1402,18 +1489,20 @@
// Parse range specifier
Vector ranges = null;
if (!resourceInfo.collection) {
+
ranges = parseRange(request, response, resourceInfo);
-
- // Last-Modified header
- if (debug > 0)
- log("DefaultServlet.serveFile: lastModified='" +
- (new Timestamp(resourceInfo.date)).toString() + "'");
- response.setDateHeader("Last-Modified", resourceInfo.date);
// ETag header
response.setHeader("ETag", getETag(resourceInfo, true));
+
}
+ // Last-Modified header
+ if (debug > 0)
+ log("DefaultServlet.serveFile: lastModified='" +
+ (new Timestamp(resourceInfo.date)).toString() + "'");
+ response.setDateHeader("Last-Modified", resourceInfo.date);
+
ServletOutputStream ostream = null;
PrintWriter writer = null;
@@ -1436,8 +1525,9 @@
}
- if ( ((ranges == null) || (ranges.isEmpty()))
- && (request.getHeader("Range") == null) ) {
+ if ( (resourceInfo.collection) ||
+ ( ((ranges == null) || (ranges.isEmpty()))
+ && (request.getHeader("Range") == null) ) ) {
// Set the appropriate output headers
if (contentType != null) {
@@ -1454,6 +1544,16 @@
response.setContentLength((int) contentLength);
}
+ if (resourceInfo.collection) {
+
+ if (content) {
+ // Serve the directory browser
+ resourceInfo.setStream
+ (render(request.getContextPath(), resourceInfo));
+ }
+
+ }
+
// Copy the input stream to our output stream (if requested)
if (content) {
try {
@@ -1667,6 +1767,184 @@
}
+ /**
+ * Return an InputStream to an HTML representation of the contents
+ * of this directory.
+ *
+ * @param contextPath Context path to which our internal paths are
+ * relative
+ */
+ private InputStream render(String contextPath, ResourceInfo resourceInfo) {
+
+ String name = resourceInfo.path;
+
+ // Number of characters to trim from the beginnings of filenames
+ int trim = name.length();
+ if (!name.endsWith("/"))
+ trim += 1;
+ if (name.equals("/"))
+ trim = 1;
+
+ // Prepare a writer to a buffered area
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ PrintWriter writer = new PrintWriter(stream);
+
+ // FIXME - Currently pays no attention to the user's Locale
+
+ // Render the page header
+ writer.print("<html>\r\n");
+ writer.print("<head>\r\n");
+ writer.print("<title>");
+ writer.print(sm.getString("directory.title", name));
+ writer.print("</title>\r\n</head>\r\n");
+ writer.print("<body bgcolor=\"white\">\r\n");
+ writer.print("<table width=\"90%\" cellspacing=\"0\"" +
+ " cellpadding=\"5\" align=\"center\">\r\n");
+
+ // Render the in-page title
+ writer.print("<tr><td colspan=\"3\"><font size=\"+2\">\r\n<strong>");
+ writer.print(sm.getString("directory.title", name));
+ writer.print("</strong>\r\n</font></td></tr>\r\n");
+
+ // Render the link to our parent (if required)
+ String parentDirectory = name;
+ if (parentDirectory.endsWith("/")) {
+ parentDirectory =
+ parentDirectory.substring(0, parentDirectory.length() - 1);
+ }
+ int slash = parentDirectory.lastIndexOf("/");
+ if (slash >= 0) {
+ String parent = name.substring(0, slash);
+ writer.print("<tr><td colspan=\"3\" bgcolor=\"#ffffff\">\r\n");
+ writer.print("<a href=\"");
+ writer.print(rewriteUrl(contextPath));
+ if (parent.equals(""))
+ parent = "/";
+ //if (contextPath.endsWith("/"))
+ //parent = parent.substring(1);
+ writer.print(rewriteUrl(parent));
+ writer.print("\">");
+ writer.print(sm.getString("directory.parent", parent));
+ writer.print("</a>\r\n");
+ writer.print("</td></tr>\r\n");
+ }
+
+ // Render the column headings
+ writer.print("<tr bgcolor=\"#cccccc\">\r\n");
+ writer.print("<td align=\"left\"><font size=\"+1\"><strong>");
+ writer.print(sm.getString("directory.filename"));
+ writer.print("</strong></font></td>\r\n");
+ writer.print("<td align=\"center\"><font size=\"+1\"><strong>");
+ writer.print(sm.getString("directory.size"));
+ writer.print("</strong></font></td>\r\n");
+ writer.print("<td align=\"right\"><font size=\"+1\"><strong>");
+ writer.print(sm.getString("directory.lastModified"));
+ writer.print("</strong></font></td>\r\n");
+ writer.print("</tr>\r\n");
+
+ try {
+
+ // Render the directory entries within this directory
+ DirContext directory = resourceInfo.directory;
+ NamingEnumeration enum =
+ resourceInfo.resources.list(resourceInfo.path);
+ boolean shade = false;
+ while (enum.hasMoreElements()) {
+
+ NameClassPair ncPair = (NameClassPair) enum.nextElement();
+ String resourceName = ncPair.getName();
+ ResourceInfo childResourceInfo =
+ new ResourceInfo(resourceName, directory);
+
+ String trimmed = resourceName/*.substring(trim)*/;
+ if (trimmed.equalsIgnoreCase("WEB-INF") ||
+ trimmed.equalsIgnoreCase("META-INF"))
+ continue;
+
+ writer.print("<tr");
+ if (shade)
+ writer.print(" bgcolor=\"eeeeee\"");
+ writer.print(">\r\n");
+ shade = !shade;
+
+ writer.print("<td align=\"left\"> \r\n");
+ writer.print("<a href=\"");
+ writer.print(rewriteUrl(contextPath));
+ resourceName = rewriteUrl(name + resourceName);
+ writer.print(resourceName);
+ writer.print("\"><tt>");
+ writer.print(trimmed);
+
+ if (childResourceInfo.collection)
+ writer.print("/");
+ writer.print("</tt></a></td>\r\n");
+
+ writer.print("<td align=\"right\"><tt>");
+ if (childResourceInfo.collection)
+ writer.print(" ");
+ else
+ writer.print(renderSize(childResourceInfo.length));
+ writer.print("</tt></td>\r\n");
+
+ writer.print("<td align=\"right\"><tt>");
+ writer.print(renderLastModified(childResourceInfo.date));
+ writer.print("</tt></td>\r\n");
+
+ writer.print("</tr>\r\n");
+ }
+
+ } catch (NamingException e) {
+ // Something went wrong
+ e.printStackTrace();
+ }
+
+ // Render the page footer
+ writer.print("<tr><td colspan=\"3\"> </td></tr>\r\n");
+ writer.print("<tr><td colspan=\"3\" bgcolor=\"#cccccc\">");
+ writer.print("<font size=\"-1\">");
+ writer.print(Globals.SERVER_INFO);
+ writer.print("</font></td></tr>\r\n");
+ writer.print("</table>\r\n");
+ writer.print("</body>\r\n");
+ writer.print("</html>\r\n");
+
+ // Return an input stream to the underlying bytes
+ writer.flush();
+ return (new ByteArrayInputStream(stream.toByteArray()));
+
+ }
+
+
+ /**
+ * Render the last modified date and time for the specified timestamp.
+ *
+ * @param lastModified Last modified date and time, in milliseconds since
+ * the epoch
+ */
+ private String renderLastModified(long lastModified) {
+
+ return (formats[0].format(new Date(lastModified)));
+
+ }
+
+
+ /**
+ * Render the specified file size (in bytes).
+ *
+ * @param size File size (in bytes)
+ */
+ private String renderSize(long size) {
+
+ long leftSide = size / 1024;
+ long rightSide = (size % 1024) / 103; // Makes 1 digit
+ if ((leftSide == 0) && (rightSide == 0) && (size > 0))
+ rightSide = 1;
+
+ return ("" + leftSide + "." + rightSide + " kb");
+
+ }
+
+
// ------------------------------------------------------ Range Inner Class
@@ -1684,6 +1962,12 @@
&& (start <= end) && (end < length) );
}
+ public void recycle() {
+ start = 0;
+ end = 0;
+ length = 0;
+ }
+
}
@@ -1698,22 +1982,15 @@
*
* @param pathname Path name of the file
*/
- public ResourceInfo(String path, Resources resources) {
-
- this.path = path;
- this.resources = resources;
- this.exists = resources.exists(path);
- if (exists) {
- this.creationDate = resources.getResourceCreated(path);
- this.date = resources.getResourceModified(path);
- this.httpDate = formats[0].format(new Date(date));
- this.length = resources.getResourceLength(path);
- this.collection = resources.isCollection(path);
- }
-
+ public ResourceInfo(String path, DirContext resources) {
+ set(path, resources);
}
+ public Object object;
+ public DirContext directory;
+ public Resource file;
+ public Attributes attributes;
public String path;
public long creationDate;
public String httpDate;
@@ -1721,7 +1998,75 @@
public long length;
public boolean collection;
public boolean exists;
- public Resources resources;
+ public DirContext resources;
+ protected InputStream is;
+
+
+ public void recycle() {
+ object = null;
+ directory = null;
+ file = null;
+ attributes = null;
+ path = null;
+ creationDate = 0;
+ httpDate = null;
+ date = 0;
+ length = -1;
+ collection = true;
+ exists = false;
+ resources = null;
+ is = null;
+ }
+
+
+ public void set(String path, DirContext resources) {
+
+ recycle();
+
+ this.path = path;
+ this.resources = resources;
+ exists = true;
+ try {
+ object = resources.lookup(path);
+ if (object instanceof Resource) {
+ file = (Resource) object;
+ collection = false;
+ } else if (object instanceof DirContext) {
+ directory = (DirContext) object;
+ collection = true;
+ } else {
+ // Don't know how to serve another object type
+ exists = false;
+ }
+ } catch (NamingException e) {
+ exists = false;
+ }
+ if (exists) {
+ try {
+ attributes = resources.getAttributes(path);
+ if (attributes instanceof ResourceAttributes) {
+ ResourceAttributes tempAttrs =
+ (ResourceAttributes) attributes;
+ Date tempDate = tempAttrs.getCreationDate();
+ if (tempDate != null)
+ creationDate = tempDate.getTime();
+ tempDate = tempAttrs.getLastModified();
+ if (tempDate != null) {
+ date = tempDate.getTime();
+ httpDate = formats[0].format(tempDate);
+ } else {
+ httpDate = formats[0].format(new Date());
+ }
+ length = tempAttrs.getContentLength();
+ }
+ } catch (NamingException e) {
+ // Shouldn't happen, the implementation of the DirContext
+ // is probably broken
+ exists = false;
+ }
+ }
+
+ }
/**
@@ -1737,6 +2082,28 @@
*/
public String toString() {
return path;
+ }
+
+
+ /**
+ * Set IS.
+ */
+ public void setStream(InputStream is) {
+ this.is = is;
+ }
+
+
+ /**
+ * Get IS from resource.
+ */
+ public InputStream getStream()
+ throws IOException {
+ if (is != null)
+ return is;
+ if (file != null)
+ return (file.streamContent());
+ else
+ return null;
}
1.4 +6 -0 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/LocalStrings.properties
Index: LocalStrings.properties
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/LocalStrings.properties,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- LocalStrings.properties 2000/11/10 01:19:17 1.3
+++ LocalStrings.properties 2001/01/23 04:47:57 1.4
@@ -19,3 +19,9 @@
managerServlet.reloaded=OK - Reloaded application at context path {0}
managerServlet.undeployed=OK - Undeployed application at context path {0}
webdavservlet.jaxpfailed=JAXP initialization failed
+directory.filename=Filename
+directory.lastModified=Last Modified
+directory.parent=Up To {0}
+directory.size=Size
+directory.title=Directory Listing For {0}
+directory.version=Tomcat Catalina version 4.1
\ No newline at end of file
1.10 +254 -101 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/WebdavServlet.java
Index: WebdavServlet.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/WebdavServlet.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- WebdavServlet.java 2001/01/18 18:57:37 1.9
+++ WebdavServlet.java 2001/01/23 04:47:57 1.10
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/WebdavServlet.java,v 1.9 2001/01/18 18:57:37 remm Exp $
- * $Revision: 1.9 $
- * $Date: 2001/01/18 18:57:37 $
+ * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/WebdavServlet.java,v 1.10 2001/01/23 04:47:57 remm Exp $
+ * $Revision: 1.10 $
+ * $Date: 2001/01/23 04:47:57 $
*
* ====================================================================
*
@@ -88,6 +88,11 @@
import java.text.SimpleDateFormat;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
@@ -95,25 +100,23 @@
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Element;
-import org.w3c.dom.Document;
-import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-import org.apache.catalina.Resources;
-import org.apache.catalina.core.ApplicationContext;
-import org.apache.catalina.resources.ResourceBean;
-import org.apache.catalina.resources.DirectoryBean;
+import javax.naming.NamingException;
+import javax.naming.InitialContext;
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NameClassPair;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import org.apache.naming.resources.Resource;
+import org.apache.naming.resources.ResourceAttributes;
import org.apache.catalina.util.MD5Encoder;
import org.apache.catalina.util.StringManager;
import org.apache.catalina.util.XMLWriter;
import org.apache.catalina.util.DOMWriter;
-import org.apache.catalina.util.xml.SaxContext;
-import org.apache.catalina.util.xml.XmlAction;
-import org.apache.catalina.util.xml.XmlMapper;
/**
@@ -121,7 +124,7 @@
* are handled by the DefaultServlet.
*
* @author Remy Maucherat
- * @version $Revision: 1.9 $ $Date: 2001/01/18 18:57:37 $
+ * @version $Revision: 1.10 $ $Date: 2001/01/23 04:47:57 $
*/
public class WebdavServlet
@@ -351,12 +354,23 @@
resp.addHeader("DAV", "1,2");
String methodsAllowed = null;
- // Retrieve the Catalina context
- ApplicationContext context = (ApplicationContext) getServletContext();
+ // Retrieve the resources
+ DirContext resources = getResources();
- Resources resources = context.getResources();
+ if (resources == null) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
+ }
- if (!resources.exists(path)) {
+ boolean exists = true;
+ Object object = null;
+ try {
+ object = resources.lookup(path);
+ } catch (NamingException e) {
+ exists = false;
+ }
+
+ if (!exists) {
methodsAllowed = "OPTIONS, MKCOL, PUT, LOCK";
resp.addHeader("Allow", methodsAllowed);
return;
@@ -364,7 +378,7 @@
methodsAllowed = "OPTIONS, GET, HEAD, POST, DELETE, TRACE, "
+ "PROPFIND, PROPPATCH, COPY, MOVE, LOCK, UNLOCK";
- if (!resources.isCollection(path)) {
+ if (!(object instanceof DirContext)) {
methodsAllowed += ", PUT";
}
@@ -469,12 +483,23 @@
}
- // Retrieve the Catalina context
- ApplicationContext context = (ApplicationContext) getServletContext();
-
- Resources resources = context.getResources();
+ // Retrieve the resources
+ DirContext resources = getResources();
+
+ if (resources == null) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ boolean exists = true;
+ Object object = null;
+ try {
+ object = resources.lookup(path);
+ } catch (NamingException e) {
+ exists = false;
+ }
- if (!resources.exists(path)) {
+ if (!exists) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
return;
}
@@ -488,7 +513,7 @@
generatedXML.writeElement(null, "multistatus"
+ generateNamespaceDeclarations(),
XMLWriter.OPENING);
-
+
if (depth == 0) {
parseProperties(req, resources, generatedXML, path, type,
properties);
@@ -506,14 +531,29 @@
parseProperties(req, resources, generatedXML, currentPath,
type, properties);
- if (resources.isCollection(currentPath)) {
- String[] children =
- resources.getCollectionMembers(currentPath);
-
- if (children != null) {
- for (int i=0; i<children.length; i++) {
- stackBelow.push(children[i]);
+ try {
+ object = resources.lookup(currentPath);
+ } catch (NamingException e) {
+ continue;
+ }
+ if (object instanceof DirContext) {
+ try {
+ NamingEnumeration enum = resources.list(currentPath);
+ while (enum.hasMoreElements()) {
+ NameClassPair ncPair =
+ (NameClassPair) enum.nextElement();
+ String newPath = currentPath;
+ if (!newPath.equals("/"))
+ newPath += "/";
+ newPath += ncPair.getName();
+ stackBelow.push(newPath);
}
+ } catch (NamingException e) {
+ e.printStackTrace();
+ resp.sendError
+ (HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+ path);
+ return;
}
if (depth > 0) {
@@ -543,7 +583,7 @@
}
}
-
+
generatedXML.writeElement(null, "multistatus",
XMLWriter.CLOSING);
@@ -594,19 +634,35 @@
String path = getRelativePath(req);
- // Retrieve the Catalina context
- ApplicationContext context = (ApplicationContext) getServletContext();
-
- Resources resources = context.getResources();
+ // Retrieve the resources
+ DirContext resources = getResources();
+ if (resources == null) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ 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 (resources.exists(path)) {
+ if (exists) {
resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED);
return;
}
- boolean result = resources.createCollection(path);
+ boolean result = true;
+ try {
+ resources.createSubcontext(path);
+ } catch (NamingException e) {
+ result = false;
+ }
if (!result) {
resp.sendError(WebdavStatus.SC_CONFLICT,
@@ -914,11 +970,22 @@
lock.path = path;
- // Retrieve the Catalina context
- ApplicationContext context = (ApplicationContext) getServletContext();
+ // Retrieve the resources
+ DirContext resources = getResources();
- Resources resources = context.getResources();
+ if (resources == null) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
+ }
+ boolean exists = true;
+ Object object = null;
+ try {
+ object = resources.lookup(path);
+ } catch (NamingException e) {
+ exists = false;
+ }
+
Enumeration locksList = null;
if (lockRequestType == LOCK_CREATION) {
@@ -932,7 +999,7 @@
String lockToken =
md5Encoder.encode(md5Helper.digest(lockTokenStr.getBytes()));
- if ( (resources.exists(path)) && (resources.isCollection(path)) &&
+ if ( (exists) && (object instanceof DirContext) &&
(lock.depth == INFINITY) ) {
// Locking a collection (and all its member resources)
@@ -1058,7 +1125,7 @@
LockInfo presentLock = (LockInfo) resourceLocks.get(lock.path);
if (presentLock != null) {
- if ( (presentLock.isExclusive()) || (lock.isExclusive()) ) {
+ if ((presentLock.isExclusive()) || (lock.isExclusive())) {
// If either lock is exclusive, the lock can't be
// granted
resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
@@ -1074,7 +1141,13 @@
resourceLocks.put(lock.path, lock);
// Checking if a resource exists at this path
- if (!resources.exists(lock.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('/');
@@ -1417,15 +1490,25 @@
// Overwriting the destination
- // Retrieve the Catalina context
- ApplicationContext context = (ApplicationContext) getServletContext();
+ // Retrieve the resources
+ DirContext resources = getResources();
- Resources resources = context.getResources();
+ if (resources == null) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return false;
+ }
+ boolean exists = true;
+ try {
+ resources.lookup(destinationPath);
+ } catch (NamingException e) {
+ exists = false;
+ }
+
if (overwrite) {
// Delete destination resource, if it exists
- if (resources.exists(destinationPath)) {
+ if (exists) {
if (!deleteResource(destinationPath, req, resp)) {
return false;
} else {
@@ -1438,7 +1521,7 @@
} else {
// If the destination exists, then it's a conflict
- if (resources.exists(destinationPath)) {
+ if (exists) {
resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
return false;
}
@@ -1477,28 +1560,60 @@
* @param source Path of the resource to be copied
* @param dest Destination path
*/
- private boolean copyResource(Resources resources, Hashtable errorList,
+ private boolean copyResource(DirContext resources, Hashtable errorList,
String source, String dest) {
+
+ if (debug > 1)
+ System.out.println("Copy: " + source + " To: " + dest);
- if (resources.isCollection(source)) {
+ Object object = null;
+ try {
+ object = resources.lookup(source);
+ } catch (NamingException e) {
+ }
+
+ if (object instanceof DirContext) {
- if (!resources.createCollection(dest)) {
+ try {
+ resources.createSubcontext(dest);
+ } catch (NamingException e) {
errorList.put
- (dest,
- new Integer(WebdavStatus.SC_CONFLICT));
+ (dest, new Integer(WebdavStatus.SC_CONFLICT));
return false;
}
- String[] members = resources.getCollectionMembers(source);
- for (int i=0; i<members.length; i++) {
- String childDest = dest +
- members[i].substring(source.length());
- copyResource(resources, errorList, members[i], childDest);
+
+ try {
+ NamingEnumeration enum = resources.list(source);
+ while (enum.hasMoreElements()) {
+ NameClassPair ncPair = (NameClassPair) enum.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 {
- InputStream is = resources.getResourceAsStream(source);
- if (!resources.setResource(dest, is)) {
+ 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));
@@ -1554,20 +1669,33 @@
return false;
}
- // Retrieve the Catalina context
- ApplicationContext context = (ApplicationContext) getServletContext();
-
- Resources resources = context.getResources();
+ // Retrieve the resources
+ DirContext resources = getResources();
- if (!resources.exists(path)) {
+ if (resources == null) {
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ 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 = resources.isCollection(path);
+ boolean collection = (object instanceof DirContext);
if (!collection) {
- if (!resources.deleteResource(path)) {
+ try {
+ resources.unbind(path);
+ } catch (NamingException e) {
resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
return false;
}
@@ -1576,7 +1704,12 @@
Hashtable errorList = new Hashtable();
deleteCollection(req, resources, path, errorList);
- resources.deleteResource(path);
+ try {
+ resources.unbind(path);
+ } catch (NamingException e) {
+ errorList.put(path, new Integer
+ (WebdavStatus.SC_INTERNAL_SERVER_ERROR));
+ }
if (!errorList.isEmpty()) {
@@ -1600,7 +1733,8 @@
* @param path Path to the collection to be deleted
* @param errorList Contains the list of the errors which occured
*/
- private void deleteCollection(HttpServletRequest req, Resources resources,
+ private void deleteCollection(HttpServletRequest req,
+ DirContext resources,
String path, Hashtable errorList) {
String ifHeader = req.getHeader("If");
@@ -1611,31 +1745,50 @@
if (lockTokenHeader == null)
lockTokenHeader = "";
- String[] members = resources.getCollectionMembers(path);
+ Enumeration enum = null;
+ try {
+ enum = resources.list(path);
+ } catch (NamingException e) {
+ errorList.put(path, new Integer
+ (WebdavStatus.SC_INTERNAL_SERVER_ERROR));
+ return;
+ }
- for (int i=0; i<members.length; i++) {
+ while (enum.hasMoreElements()) {
+ NameClassPair ncPair = (NameClassPair) enum.nextElement();
+ String childName = path;
+ if (!childName.equals("/"))
+ childName += "/";
+ childName += ncPair.getName();
- if (isLocked(members[i], ifHeader + lockTokenHeader)) {
+ if (isLocked(childName, ifHeader + lockTokenHeader)) {
- errorList.put(members[i], new Integer(WebdavStatus.SC_LOCKED));
+ errorList.put(childName, new Integer(WebdavStatus.SC_LOCKED));
} else {
-
- if (resources.isCollection(members[i])) {
- deleteCollection(req, resources, members[i], errorList);
- }
- boolean result = resources.deleteResource(members[i]);
- if (!result) {
- if (!resources.isCollection(members[i])) {
- // If it's not a collection, then it's an unknown
- // error
- errorList.put
- (members[i], new Integer
- (WebdavStatus.SC_INTERNAL_SERVER_ERROR));
+ 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));
}
-
}
}
@@ -1711,7 +1864,7 @@
* name, then this Vector contains those properties
*/
private void parseProperties(HttpServletRequest req,
- Resources resources, XMLWriter generatedXML,
+ DirContext resources, XMLWriter generatedXML,
String path, int type,
Vector propertiesVector) {
@@ -1731,15 +1884,15 @@
// Generating href element
generatedXML.writeElement(null, "href", XMLWriter.OPENING);
- String absoluteUri = req.getRequestURI();
- String relativePath = normalize(getRelativePath(req));
- String toAppend = path.substring(relativePath.length());
- if ((!toAppend.startsWith("/")) && (!absoluteUri.endsWith("/")))
- toAppend = "/" + toAppend;
- if (toAppend.equals("/"))
- toAppend = "";
+ String href = req.getContextPath();
+ if ((href.endsWith("/")) && (path.startsWith("/")))
+ href += path.substring(1);
+ else
+ href += path;
+ if ((resourceInfo.collection) && (!href.endsWith("/")))
+ href += "/";
- generatedXML.writeText(absoluteUri + toAppend);
+ generatedXML.writeText(rewriteUrl(href));
generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
@@ -2004,9 +2157,9 @@
if (!toAppend.startsWith("/"))
toAppend = "/" + toAppend;
- generatedXML.writeText(absoluteUri + toAppend);
+ generatedXML.writeText(rewriteUrl(absoluteUri + toAppend));
- generatedXML.writeElement("d", "href", XMLWriter.CLOSING);
+ generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
switch (type) {