/*
* $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/WebdavServlet.java,v 1.24 2001/08/25 14:18:57 dirkv Exp $
* $Revision: 1.24 $
* $Date: 2001/08/25 14:18:57 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.slide.webdav;
import java.io.*;
import java.net.URL;
import java.security.Principal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import org.apache.util.WebdavStatus;
import org.apache.util.DOMUtils;
import org.apache.slide.authenticate.SecurityToken;
import org.apache.slide.common.*;
import org.apache.slide.content.Content;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.lock.Lock;
import org.apache.slide.lock.NodeLock;
import org.apache.slide.security.AccessDeniedException;
import org.apache.slide.security.NodePermission;
import org.apache.slide.security.Security;
import org.apache.slide.structure.LinkedObjectNotFoundException;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.structure.Structure;
import org.apache.slide.util.conf.*;
import org.apache.slide.util.Messages;
import org.apache.slide.util.logger.Logger;
import org.apache.slide.webdav.logger.XHttpServletRequestFacade;
import org.apache.slide.webdav.logger.XHttpServletResponseFacade;
import org.apache.slide.webdav.logger.XMLTestCaseGenerator;
import org.apache.slide.webdav.method.*;
/**
* WebDAV Servlet.
*
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
* @author Dirk Verbeeck
* @version $Revision: 1.24 $
*/
public class WebdavServlet extends HttpServlet {
// -------------------------------------------------------------- Constants
/**
* HTTP Date format pattern (RFC 2068, 822, 1123).
*/
public static final String DATE_FORMAT = "EEE, d MMM yyyy kk:mm:ss z";
/**
* Date formatter.
*/
private static final DateFormat formatter =
new SimpleDateFormat(DATE_FORMAT);
// ----------------------------------------------------- Instance Variables
/**
* Access token to the namespace.
*/
protected NamespaceAccessToken token;
/**
* Directory browsing enabled.
*/
protected boolean directoryBrowsing = true;
// ------------------------------------------------------ Protected Methods
/**
* Create Slide Method form the HTTP Method.
*
* @return WebdavMethod
* @exception WebdavException
*/
protected WebdavMethod createWebdavMethod
(HttpServletRequest req, HttpServletResponse resp)
throws WebdavException {
String methodName = req.getMethod();
WebdavMethod resultMethod = null;
WebdavServletConfig config = (WebdavServletConfig)getServletConfig();
if (methodName.equalsIgnoreCase("GET")) {
resultMethod = new GetMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("PROPFIND")) {
resultMethod = new PropFindMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("HEAD")) {
resultMethod = new HeadMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("LOCK")) {
resultMethod = new LockMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("UNLOCK")) {
resultMethod = new UnlockMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("OPTIONS")) {
resultMethod = new OptionsMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("PUT")) {
resultMethod = new PutMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("MKCOL")) {
resultMethod = new MkcolMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("POST")) {
resultMethod = new PostMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("COPY")) {
resultMethod = new CopyMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("MOVE")) {
resultMethod = new MoveMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("DELETE")) {
resultMethod = new DeleteMethod(token, req, resp, config);
} else if (methodName.equalsIgnoreCase("PROPPATCH")) {
resultMethod = new PropPatchMethod(token, req, resp,config);
} else if (methodName.equalsIgnoreCase("ACL")) {
if( org.apache.slide.util.Configuration.useIntegratedSecurity() )
resultMethod = new AclMethod(token, req, resp, config);
}
if (resultMethod == null) {
throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
}
return resultMethod;
}
// -------------------------------------------------------- Servlet Methods
protected void service (HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
// if logging for the request/response is required initialise the
// facades
if (Domain.isEnabled
("org.apache.slide.webdav.WebdavServlet.requestResponseLogger",
Logger.DEBUG)) {
if ( req != null ) req = new XHttpServletRequestFacade(req);
if ( resp != null ) resp = new XHttpServletResponseFacade(resp);
}
resp.setStatus(WebdavStatus.SC_OK);
if (token == null) {
String namespaceName = req.getContextPath();
if ((namespaceName == null) || (namespaceName.equals("")))
namespaceName = Domain.getDefaultNamespace();
while (namespaceName.startsWith("/"))
namespaceName = namespaceName.substring(1);
token = Domain.accessNamespace
(new SecurityToken(this), namespaceName);
}
try {
String methodName = req.getMethod();
WebdavServletConfig config =
(WebdavServletConfig)getServletConfig();
if ((methodName.equalsIgnoreCase("GET") ||
methodName.equalsIgnoreCase("POST")) &&
WebdavUtils.isCollection(token, req, config)) {
// let the standard doGet() / doPost() methods handle
// GET/POST requests on collections (to display a directory
// index pag or something similar)
super.service(req, resp);
} else {
WebdavMethod method = createWebdavMethod(req, resp);
method.run();
}
} catch (WebdavException e) {
// There has been an error somewhere ...
resp.sendError(e.getStatusCode());
System.out.println(e.getMessage());
e.printStackTrace();
} catch (Throwable e) {
// If something goes really wrong ...
resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
e.printStackTrace();
}
// if logging for the request/response is required perform the logging
if (Domain.isEnabled
("org.apache.slide.webdav.WebdavServlet.requestResponseLogger",
Logger.DEBUG)) {
XMLTestCaseGenerator xmlGen = new XMLTestCaseGenerator
((XHttpServletRequestFacade)req,
(XHttpServletResponseFacade)resp);
xmlGen.setThreadName(Thread.currentThread().getName());
Domain.log
(xmlGen.toString(),
"org.apache.slide.webdav.WebdavServlet.requestResponseLogger",
Logger.DEBUG);
}
Domain.info
(req.getMethod()
+ ( (resp instanceof XHttpServletResponseFacade)
? (" = " + ((XHttpServletResponseFacade)resp)
.getStatus()
+ " " + (WebdavStatus.getStatusText
(((XHttpServletResponseFacade)resp)
.getStatus())))
: ("") )
+ " (time: " + (System.currentTimeMillis() - startTime)
+ " ms)"
+ " URI = " + WebdavUtils.getRelativePath(
req, (WebdavServletConfig)getServletConfig()));
}
/**
* Implemented to wrap the ServletConfig object inside a
* WebdavServletConfig
*/
public void init(
ServletConfig config)
throws ServletException {
super.init(new WebdavServletConfig(config));
// all the actual initialization is inside init()
}
/**
* Manages some initialization stuff on the server.
*/
public void init()
throws ServletException {
if (!DOMUtils.isDocumentBuilderDOM2Compliant()) {
System.out.println("======================================================");
System.out.println("!!! Unable to start Slide Servlet !!!");
System.out.println("------------------------------------------------------");
System.out.println("You are using using an incorrect older XML parser");
System.out.println("that doesn't provide Element::getElementsByTagNameNS");
System.out.println("consult the documentation for a list of valid XML parsers.");
System.out.println("======================================================");
log("======================================================");
log("!!! Unable to start Slide Servlet !!!");
log("------------------------------------------------------");
log("======================================================");
log("You are using using an incorrect older XML parser");
log("that doesn't provide Element::getElementsByTagNameNS");
log("consult the documentation for a list of valid XML parsers.");
log("======================================================");
throw new ServletException("Invalid XML parser");
}
String namespaceName = null;
String domainConfigFile = null;
String value = null;
try {
value = getInitParameter("namespace");
if (value != null)
namespaceName = value;
} catch (Throwable t) {
;
}
try {
value = getInitParameter("domain");
if (value != null)
domainConfigFile = value;
} catch (Throwable t) {
;
}
try {
value = getInitParameter("directory-browsing");
if (value != null) {
directoryBrowsing = new Boolean(value).booleanValue();
}
} catch (Throwable t) {
;
}
try {
if (domainConfigFile != null) {
URL domainConfigFileURL =
getServletContext().getResource(domainConfigFile);
if (domainConfigFileURL != null) {
Domain.init(domainConfigFileURL);
}
}
if (namespaceName == null) {
namespaceName = Domain.getDefaultNamespace();
log("No namespace specified, will use default namespace: " +
namespaceName);
}
token = Domain.accessNamespace
(new SecurityToken(this), namespaceName);
if (token == null) {
log("Could not access namespace " + namespaceName + ".");
throw new UnavailableException("Namespace " + namespaceName +
" not accessible");
}
} catch (DomainInitializationFailedError e) {
log("Could not initialize domain", e);
throw new UnavailableException(e.getMessage());
} catch (Throwable t) {
t.printStackTrace();
throw new ServletException(t.getMessage());
}
}
/**
* Destroy servlet.
*/
public void destroy() {
Domain.closeNamespace(token);
}
// ------------------------------------------------------ Protected Methods
/**
* Handle a GET request on a collection resource.
*/
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (directoryBrowsing) {
Writer writer = resp.getWriter();
resp.setContentType("text/html");
try {
displayDirectoryBrowsing(req, writer);
} catch (AccessDeniedException e) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
} catch (ObjectNotFoundException e) {
resp.sendError(WebdavStatus.SC_NOT_FOUND);
} catch (LinkedObjectNotFoundException e) {
resp.sendError(WebdavStatus.SC_NOT_FOUND);
} catch (SlideException e) {
resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
}
} else {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
}
}
/**
* Display a directory browsing page.
*/
protected void displayDirectoryBrowsing(HttpServletRequest req,
Writer servletWriter)
throws IOException, SlideException {
String contextPath = req.getContextPath();
if (contextPath == null)
contextPath = "";
// get the helpers
Content content = token.getContentHelper();
Lock lock = token.getLockHelper();
Security security = token.getSecurityHelper();
Structure structure = token.getStructureHelper();
SlideToken slideToken = WebdavUtils.getSlideToken(req);
String resourcePath =
WebdavUtils.getRelativePath(
req, (WebdavServletConfig)getServletConfig());
ObjectNode object = structure.retrieve(slideToken, resourcePath);
String name = object.getUri();
// Number of characters to trim from the beginnings of filenames
int trim = name.length();
if (!name.endsWith("/"))
trim += 1;
if (name.equals("/"))
trim = 1;
PrintWriter writer = new PrintWriter(servletWriter);
// Render the page header
writer.print("<html>\r\n");
writer.print("<head>\r\n");
writer.print("<title>");
writer.print
(Messages.format
("org.apache.slide.webdav.GetMethod.directorylistingfor", 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
(Messages.format
("org.apache.slide.webdav.GetMethod.directorylistingfor", 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);
}
String scope = ((WebdavServletConfig)getServletConfig()).getScope();
if (parentDirectory.substring(scope.length()).lastIndexOf("/") >= 0) {
String parent = name.substring(0, name.lastIndexOf("/"));
writer.print("<tr><td colspan=\"5\" bgcolor=\"#ffffff\">\r\n");
writer.print("<a href=\"");
writer.print(WebdavUtils.encodeURL(contextPath));
if (parent.equals(""))
parent = "/";
writer.print(parent);
writer.print("\">");
writer.print(Messages.format
("org.apache.slide.webdav.GetMethod.parent", parent));
writer.print("</a>\r\n");
writer.print("</td></tr>\r\n");
}
Enumeration permissionsList = null;
Enumeration locksList = null;
try {
permissionsList =
security.enumeratePermissions(slideToken, object.getUri());
locksList = lock.enumerateLocks(slideToken, object.getUri());
} catch (SlideException e) {
// Any security based exception will be trapped here
// Any locking based exception will be trapped here
}
// Displaying ACL info
if( org.apache.slide.util.Configuration.useIntegratedSecurity() )
displayPermissions(permissionsList, writer, false);
// Displaying lock info
displayLocks(locksList, writer, false);
writer.print("<tr><td colspan=\"5\" bgcolor=\"#ffffff\">");
writer.print(" ");
writer.print("</td></tr>\r\n");
// Render the column headings
writer.print("<tr bgcolor=\"#cccccc\">\r\n");
writer.print("<td align=\"left\" colspan=\"3\">");
writer.print("<font size=\"+1\"><strong>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.filename"));
writer.print("</strong></font></td>\r\n");
writer.print("<td align=\"center\"><font size=\"+1\"><strong>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.size"));
writer.print("</strong></font></td>\r\n");
writer.print("<td align=\"right\"><font size=\"+1\"><strong>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.lastModified"));
writer.print("</strong></font></td>\r\n");
writer.print("</tr>\r\n");
Enumeration resources = object.enumerateChildren();
boolean shade = false;
while (resources.hasMoreElements()) {
String currentResource = (String) resources.nextElement();
NodeRevisionDescriptor currentDescriptor = null;
permissionsList = null;
locksList = null;
try {
NodeRevisionDescriptors revisionDescriptors =
content.retrieve(slideToken, currentResource);
// Retrieve latest revision descriptor
currentDescriptor =
content.retrieve(slideToken, revisionDescriptors);
} catch (SlideException e) {
// Silent exception : Objects without any revision are
// considered collections, and do not have any attributes
// Any security based exception will be trapped here
// Any locking based exception will be trapped here
}
try {
permissionsList =
security.enumeratePermissions(slideToken, currentResource);
locksList = lock.enumerateLocks(slideToken, currentResource);
} catch (SlideException e) {
// Any security based exception will be trapped here
// Any locking based exception will be trapped here
}
String trimmed = currentResource.substring(trim);
if (trimmed.equalsIgnoreCase("WEB-INF") ||
trimmed.equalsIgnoreCase("META-INF"))
continue;
writer.print("<tr");
if (shade) {
writer.print(" bgcolor=\"dddddd\"");
} else {
writer.print(" bgcolor=\"eeeeee\"");
}
writer.print(">\r\n");
shade = !shade;
writer.print("<td align=\"left\" colspan=\"3\"> \r\n");
writer.print("<a href=\"");
writer.print(WebdavUtils.encodeURL(contextPath + currentResource));
writer.print("\"><tt>");
writer.print(trimmed);
if (WebdavUtils.isCollection(currentDescriptor)) {
writer.print("/");
}
writer.print("</tt></a></td>\r\n");
writer.print("<td align=\"right\"><tt>");
if (WebdavUtils.isCollection(currentDescriptor))
writer.print(" ");
else
writer.print(renderSize(currentDescriptor.getContentLength()));
writer.print("</tt></td>\r\n");
writer.print("<td align=\"right\"><tt>");
if (currentDescriptor != null) {
writer.print(currentDescriptor.getLastModified());
} else {
writer.print(" ");
}
writer.print("</tt></td>\r\n");
writer.print("</tr>\r\n");
// Displaying ACL info
if( org.apache.slide.util.Configuration.useIntegratedSecurity() )
displayPermissions(permissionsList, writer, shade);
// Displaying lock info
displayLocks(locksList, writer, shade);
}
// Render the page footer
writer.print("<tr><td colspan=\"5\"> </td></tr>\r\n");
writer.print("<tr><td colspan=\"3\" bgcolor=\"#cccccc\">");
writer.print("<font size=\"-1\">");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.version"));
writer.print("</font></td>\r\n");
writer.print("<td colspan=\"2\" align=\"right\" bgcolor=\"#cccccc\">");
writer.print("<font size=\"-1\">");
writer.print(formatter.format(new Date()));
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();
}
/**
* Display an ACL list.
*
* @param permissionsList List of NodePermission objects
* @param shade
* @param writer The output will be appended to this writer
*/
private void displayPermissions(Enumeration permissionsList,
PrintWriter writer,
boolean shade)
throws IOException {
if ((permissionsList != null) && (permissionsList.hasMoreElements())) {
writer.print("<tr" + (shade ? " bgcolor=\"eeeeee\""
: " bgcolor=\"dddddd\"") +
">\r\n");
writer.print("<td align=\"left\" colspan=\"5\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.aclinfo"));
writer.print("</b></tt></td>\r\n");
writer.print("</tr>\r\n");
writer.print("<tr");
if (!shade) {
writer.print(" bgcolor=\"dddddd\"");
} else {
writer.print(" bgcolor=\"eeeeee\"");
}
writer.print(">\r\n");
writer.print("<td align=\"left\" colspan=\"2\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.subject"));
writer.print("</b></tt></td>\r\n");
writer.print("<td align=\"left\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.action"));
writer.print("</b></tt></td>\r\n");
writer.print("<td align=\"right\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.inheritable"));
writer.print("</b></tt></td>\r\n");
writer.print("<td align=\"right\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.deny"));
writer.print("</b></tt></td>\r\n");
writer.print("</tr>\r\n");
while (permissionsList.hasMoreElements()) {
writer.print("<tr" + (shade ? " bgcolor=\"eeeeee\""
: " bgcolor=\"dddddd\"") +
">\r\n");
NodePermission currentPermission =
(NodePermission) permissionsList.nextElement();
writer.print("<td align=\"left\" colspan=\"2\"><tt>");
writer.print(currentPermission.getSubjectUri());
writer.print("</tt></td>\r\n");
writer.print("<td align=\"left\"><tt>");
writer.print(currentPermission.getActionUri());
writer.print("</tt></td>\r\n");
writer.print("<td align=\"right\"><tt>");
writer.print(currentPermission.isInheritable());
writer.print("</tt></td>\r\n");
writer.print("<td align=\"right\"><tt>");
writer.print(currentPermission.isNegative());
writer.print("</tt></td>\r\n");
writer.print("</tr>\r\n");
}
}
}
/**
* Display a lock list.
*
* @param locksList List of NodeLock objects
* @param shade
* @param writer The output will be appended to this writer
*/
private void displayLocks(Enumeration locksList, PrintWriter writer,
boolean shade)
throws IOException {
if ((locksList != null) && (locksList.hasMoreElements())) {
writer.print("<tr" + (shade ? " bgcolor=\"eeeeee\""
: " bgcolor=\"dddddd\"") +
">\r\n");
writer.print("<td align=\"left\" colspan=\"5\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.locksinfo"));
writer.print("</b></tt></td>\r\n");
writer.print("</tr>\r\n");
writer.print("<tr");
if (!shade) {
writer.print(" bgcolor=\"dddddd\"");
} else {
writer.print(" bgcolor=\"eeeeee\"");
}
writer.print(">\r\n");
writer.print("<td align=\"left\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.subject"));
writer.print("</b></tt></td>\r\n");
writer.print("<td align=\"left\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.type"));
writer.print("</b></tt></td>\r\n");
writer.print("<td align=\"right\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.expiration"));
writer.print("</b></tt></td>\r\n");
writer.print("<td align=\"right\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.inheritable"));
writer.print("</b></tt></td>\r\n");
writer.print("<td align=\"right\"><tt><b>");
writer.print(Messages.message
("org.apache.slide.webdav.GetMethod.exclusive"));
writer.print("</b></tt></td>\r\n");
writer.print("</tr>\r\n");
while (locksList.hasMoreElements()) {
writer.print("<tr" + (shade ? " bgcolor=\"eeeeee\""
: " bgcolor=\"dddddd\"") +
">\r\n");
NodeLock currentLock = (NodeLock) locksList.nextElement();
writer.print("<td align=\"left\"><tt>");
writer.print(currentLock.getSubjectUri());
writer.print("</tt></td>\r\n");
writer.print("<td align=\"left\"><tt>");
writer.print(currentLock.getTypeUri());
writer.print("</tt></td>\r\n");
writer.print("<td align=\"right\"><tt>");
writer.print
(formatter.format(currentLock.getExpirationDate()));
writer.print("</tt></td>\r\n");
writer.print("<td align=\"right\"><tt>");
writer.print(currentLock.isInheritable());
writer.print("</tt></td>\r\n");
writer.print("<td align=\"right\"><tt>");
writer.print(currentLock.isExclusive());
writer.print("</tt></td>\r\n");
}
}
}
// -------------------------------------------------------- Private Methods
/**
* 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");
}
}