/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-06 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id$
*/
package org.exist.http.webdav;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.OutputKeys;
import org.apache.log4j.Logger;
import org.exist.EXistException;
import org.exist.http.servlets.Authenticator;
import org.exist.http.servlets.BasicAuthenticator;
import org.exist.http.servlets.DigestAuthenticator;
import org.exist.security.User;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.serializers.EXistOutputKeys;
import org.exist.util.MimeType;
import org.exist.xmldb.XmldbURI;
/**
* The main class for processing WebDAV requests.
*
* @author wolf
*/
public class WebDAV {
public final static String DAV_NS = "DAV:";
// authentication methods
public final static int BASIC_AUTH = 0;
public final static int DIGEST_AUTH = 1;
// default content types
public final static String BINARY_CONTENT = MimeType.BINARY_TYPE.getName();
public final static String XML_CONTENT = MimeType.XML_TYPE.getName();
/** id of the database registred against the BrokerPool */
protected String databaseid = BrokerPool.DEFAULT_INSTANCE_NAME;
// default output properties for the XML serialization
public final static Properties OUTPUT_PROPERTIES = new Properties();
static {
OUTPUT_PROPERTIES.setProperty(OutputKeys.INDENT, "yes");
OUTPUT_PROPERTIES.setProperty(OutputKeys.ENCODING, "UTF-8");
OUTPUT_PROPERTIES.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
OUTPUT_PROPERTIES.setProperty(EXistOutputKeys.EXPAND_XINCLUDES, "no");
OUTPUT_PROPERTIES.setProperty(EXistOutputKeys.PROCESS_XSL_PI, "no");
}
// additional response codes
public final static int SC_MULTI_STATUS = 207;
private final static Logger LOG = Logger.getLogger(WebDAV.class);
private WebDAVMethodFactory factory;
private int defaultAuthMethod;
private Authenticator digestAuth;
private Authenticator basicAuth;
private BrokerPool pool;
public WebDAV(int authenticationMethod, String id) throws ServletException {
this(authenticationMethod,id,WebDAVMethodFactory.getInstance());
}
public WebDAV(int authenticationMethod, String id,WebDAVMethodFactory factory) throws ServletException {
this.factory = factory;
if (id != null && !"".equals(id)) this.databaseid=id;
try {
pool = BrokerPool.getInstance(this.databaseid);
} catch (EXistException e) {
throw new ServletException("Error found while initializing "
+ "database: " + e.getMessage(), e);
}
defaultAuthMethod = authenticationMethod;
digestAuth = new DigestAuthenticator(pool);
basicAuth = new BasicAuthenticator(pool);
}
/**
* Process a WebDAV request. The request is delegated to the corresponding
* {@link WebDAVMethod} after authenticating the user.
*
* @param request an HttpServletRequest object that contains
* the request the client has made of the servlet
* @param response an HttpServletResponse object that contains the
* response the servlet sends to the client
* @throws ServletException if the request could not be handled
* @throws IOException if an input or output error is detected when
* the servlet handles the request
*/
public void process(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
User user = authenticate(request, response);
if(user == null){
// TODO Return error code ?
// response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
// "Please Supply credentials");
return;
}
String path = request.getPathInfo();
if(path == null || path.length() == 0 || path.equals("/")) {
response.sendRedirect(request.getRequestURI() + DBBroker.ROOT_COLLECTION);
return;
}
if(path.endsWith("/"))
path = path.substring(0, path.length() - 1);
if(LOG.isDebugEnabled()){
LOG.debug("method='" + request.getMethod() + "'; path='" + path
+ "'; user='"+user.getName()
+ "'; Lock-Token='" + request.getHeader("Lock-Token")
+ "'; If='"+request.getHeader("If")+"'");
}
// for debugging webdav
long start=System.currentTimeMillis();
WebDAVMethod method = factory.create(request.getMethod(), pool);
if(method == null) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED,
"Method is not supported: " + request.getMethod());
return;
}
try {
method.process(user, request, response, XmldbURI.xmldbUriFor(path));
} catch (URISyntaxException e) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
} catch (Throwable e){
LOG.error(e);
throw new ServletException("An error occurred: " + e.getMessage(), e);
} finally {
// for debugging webdav
if(LOG.isDebugEnabled()){
LOG.debug("Completed in "+(System.currentTimeMillis()-start)+" msecs.");
}
}
}
private User authenticate(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String credentials = request.getHeader("Authorization");
if(credentials == null) {
if(defaultAuthMethod == BASIC_AUTH)
basicAuth.sendChallenge(request, response);
else
digestAuth.sendChallenge(request, response);
return null;
}
if(credentials.toUpperCase().startsWith("DIGEST")) {
return digestAuth.authenticate(request, response);
} else {
return basicAuth.authenticate(request, response);
}
}
}