blob: 11557409f354e452b415da013b89057bb6e2e5a2 [file] [log] [blame]
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.j2ee;
import org.apache.jackrabbit.server.AbstractWebdavServlet;
import org.apache.jackrabbit.server.BasicCredentialsProvider;
import org.apache.jackrabbit.server.SessionProvider;
import org.apache.jackrabbit.server.SessionProviderImpl;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavLocatorFactory;
import org.apache.jackrabbit.webdav.DavMethods;
import org.apache.jackrabbit.webdav.DavResource;
import org.apache.jackrabbit.webdav.DavResourceFactory;
import org.apache.jackrabbit.webdav.DavSessionProvider;
import org.apache.jackrabbit.webdav.WebdavRequest;
import org.apache.jackrabbit.webdav.WebdavResponse;
import org.apache.jackrabbit.webdav.jcr.DavLocatorFactoryImpl;
import org.apache.jackrabbit.webdav.lock.LockManager;
import org.apache.jackrabbit.webdav.lock.SimpleLockManager;
import org.apache.jackrabbit.webdav.simple.DavSessionProviderImpl;
import org.apache.jackrabbit.webdav.simple.ResourceConfig;
import org.apache.jackrabbit.webdav.simple.ResourceFactoryImpl;
import org.apache.log4j.Logger;
import javax.jcr.Repository;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.IOException;
import java.net.MalformedURLException;
/**
* WebdavServlet provides webdav support (level 1 and 2 complient) for repository
* resources.
*/
public class SimpleWebdavServlet extends AbstractWebdavServlet {
/**
* the default logger
*/
private static final Logger log = Logger.getLogger(SimpleWebdavServlet.class);
/**
* init param name of the repository prefix
*/
public static final String INIT_PARAM_RESOURCE_PATH_PREFIX = "resource-path-prefix";
/**
* Name of the optional init parameter that defines the value of the
* 'WWW-Authenticate' header.<p/>
* If the parameter is omitted the default value
* {@link #DEFAULT_AUTHENTICATE_HEADER "Basic Realm=Jackrabbit Webdav Server"}
* is used.
*
* @see #getAuthenticateHeaderValue()
*/
public static final String INIT_PARAM_AUTHENTICATE_HEADER = "authenticate-header";
/** the 'missing-auth-mapping' init parameter */
public final static String INIT_PARAM_MISSING_AUTH_MAPPING = "missing-auth-mapping";
/**
* Name of the init parameter that specify a separate configuration used
* for filtering the resources displayed.
*/
public static final String INIT_PARAM_RESOURCE_CONFIG = "resource-config";
/**
* Servlet context attribute used to store the path prefix instead of
* having a static field with this servlet. The latter causes problems
* when running multiple
*/
public static final String CTX_ATTR_RESOURCE_PATH_PREFIX = "jackrabbit.webdav.simple.resourcepath";
/**
* the resource path prefix
*/
private String resourcePathPrefix;
/**
* Header value as specified in the {@link #INIT_PARAM_AUTHENTICATE_HEADER} parameter.
*/
private String authenticate_header;
/**
* Map used to remember any webdav lock created without being reflected
* in the underlying repository.
* This is needed because some clients rely on a successful locking
* mechanism in order to perform properly (e.g. mac OSX built-in dav client)
*/
private LockManager lockManager;
/**
* the resource factory
*/
private DavResourceFactory resourceFactory;
/**
* the locator factory
*/
private DavLocatorFactory locatorFactory;
/**
* the jcr repository
*/
private Repository repository;
/**
* the webdav session provider
*/
private DavSessionProvider davSessionProvider;
/**
* the repository session provider
*/
private SessionProvider sessionProvider;
/**
* The config
*/
private ResourceConfig config;
/**
* Init this servlet
*
* @throws ServletException
*/
public void init() throws ServletException {
super.init();
resourcePathPrefix = getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX);
if (resourcePathPrefix == null) {
log.debug("Missing path prefix > setting to empty string.");
resourcePathPrefix = "";
} else if (resourcePathPrefix.endsWith("/")) {
log.debug("Path prefix ends with '/' > removing trailing slash.");
resourcePathPrefix = resourcePathPrefix.substring(0, resourcePathPrefix.length() - 1);
}
getServletContext().setAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX, resourcePathPrefix);
log.info(INIT_PARAM_RESOURCE_PATH_PREFIX + " = '" + resourcePathPrefix + "'");
authenticate_header = getInitParameter(INIT_PARAM_AUTHENTICATE_HEADER);
if (authenticate_header == null) {
authenticate_header = DEFAULT_AUTHENTICATE_HEADER;
}
log.info("WWW-Authenticate header = '" + authenticate_header + "'");
String configParam = getInitParameter(INIT_PARAM_RESOURCE_CONFIG);
if (configParam != null) {
try {
config = new ResourceConfig();
config.parse(getServletContext().getResource(configParam));
} catch (MalformedURLException e) {
log.debug("Unable to build resource filter provider.");
}
}
}
/**
* Executes the respective method in the given webdav context.
* The method is overridden since not all webdav methods should be
* supported by this servlet.
*
* @param request
* @param response
* @param method
* @param resource
* @return
* @throws ServletException
* @throws IOException
* @throws org.apache.jackrabbit.webdav.DavException
*/
protected boolean execute(WebdavRequest request, WebdavResponse response,
int method, DavResource resource)
throws ServletException, IOException, DavException {
switch (method) {
case DavMethods.DAV_HEAD:
doHead(request, response, resource);
break;
case DavMethods.DAV_GET:
doGet(request, response, resource);
break;
case DavMethods.DAV_OPTIONS:
doOptions(request, response, resource);
break;
case DavMethods.DAV_PROPFIND:
doPropFind(request, response, resource);
break;
case DavMethods.DAV_PROPPATCH:
doPropPatch(request, response, resource);
break;
case DavMethods.DAV_PUT:
doPut(request, response, resource);
break;
case DavMethods.DAV_POST:
doPost(request, response, resource);
break;
case DavMethods.DAV_DELETE:
doDelete(request, response, resource);
break;
case DavMethods.DAV_COPY:
doCopy(request, response, resource);
break;
case DavMethods.DAV_MOVE:
doMove(request, response, resource);
break;
case DavMethods.DAV_MKCOL:
doMkCol(request, response, resource);
break;
case DavMethods.DAV_LOCK:
doLock(request, response, resource);
break;
case DavMethods.DAV_UNLOCK:
doUnlock(request, response, resource);
break;
default:
// any other method
return false;
}
return true;
}
/**
* {@inheritDoc}
*/
protected boolean isPreconditionValid(WebdavRequest request,
DavResource resource) {
return !resource.exists() || request.matchesIfHeader(resource);
}
/**
* Returns the configured path prefix
*
* @return resourcePathPrefix
* @see #INIT_PARAM_RESOURCE_PATH_PREFIX
*/
public String getPathPrefix() {
return resourcePathPrefix;
}
/**
* Returns the configured path prefix
*
* @return resourcePathPrefix
* @see #INIT_PARAM_RESOURCE_PATH_PREFIX
*/
public static String getPathPrefix(ServletContext ctx) {
return (String) ctx.getAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX);
}
/**
* Returns the <code>DavLocatorFactory</code>. If no locator factory has
* been set or created a new instance of {@link org.apache.jackrabbit.webdav.simple.LocatorFactoryImpl} is
* returned.
*
* @return the locator factory
* @see AbstractWebdavServlet#getLocatorFactory()
*/
public DavLocatorFactory getLocatorFactory() {
if (locatorFactory == null) {
locatorFactory = new DavLocatorFactoryImpl(resourcePathPrefix);
}
return locatorFactory;
}
/**
* Sets the <code>DavLocatorFactory</code>.
*
* @param locatorFactory
* @see AbstractWebdavServlet#setLocatorFactory(DavLocatorFactory)
*/
public void setLocatorFactory(DavLocatorFactory locatorFactory) {
this.locatorFactory = locatorFactory;
}
/**
* Returns the <code>LockManager</code>. If no lock manager has
* been set or created a new instance of {@link SimpleLockManager} is
* returned.
*
* @return the lock manager
*/
public LockManager getLockManager() {
if (lockManager == null) {
lockManager = new SimpleLockManager();
}
return lockManager;
}
/**
* Sets the <code>LockManager</code>.
*
* @param lockManager
*/
public void setLockManager(LockManager lockManager) {
this.lockManager = lockManager;
}
/**
* Returns the <code>DavResourceFactory</code>. If no request factory has
* been set or created a new instance of {@link ResourceFactoryImpl} is
* returned.
*
* @return the resource factory
* @see org.apache.jackrabbit.server.AbstractWebdavServlet#getResourceFactory()
*/
public DavResourceFactory getResourceFactory() {
if (resourceFactory == null) {
resourceFactory = new ResourceFactoryImpl(getLockManager(), getResourceConfig());
}
return resourceFactory;
}
/**
* Sets the <code>DavResourceFactory</code>.
*
* @param resourceFactory
* @see AbstractWebdavServlet#setResourceFactory(org.apache.jackrabbit.webdav.DavResourceFactory)
*/
public void setResourceFactory(DavResourceFactory resourceFactory) {
this.resourceFactory = resourceFactory;
}
/**
* Returns the <code>SessionProvider</code>. If no session provider has been
* set or created a new instance of {@link SessionProviderImpl} that extracts
* credentials from the request's <code>Authorization</code> header is
* returned.
*
* @return the session provider
*/
public synchronized SessionProvider getSessionProvider() {
if (sessionProvider == null) {
sessionProvider = new SessionProviderImpl(
new BasicCredentialsProvider(
getInitParameter(INIT_PARAM_MISSING_AUTH_MAPPING))
);
}
return sessionProvider;
}
/**
* Sets the <code>SessionProvider</code>.
*
* @param sessionProvider
*/
public synchronized void setSessionProvider(SessionProvider sessionProvider) {
this.sessionProvider = sessionProvider;
}
/**
* Returns the <code>DavSessionProvider</code>. If no session provider has
* been set or created a new instance of {@link DavSessionProviderImpl}
* is returned.
*
* @return the session provider
* @see org.apache.jackrabbit.server.AbstractWebdavServlet#getDavSessionProvider()
*/
public synchronized DavSessionProvider getDavSessionProvider() {
if (davSessionProvider == null) {
davSessionProvider =
new DavSessionProviderImpl(getRepository(), getSessionProvider());
}
return davSessionProvider;
}
/**
* Sets the <code>DavSessionProvider</code>.
*
* @param sessionProvider
* @see AbstractWebdavServlet#setDavSessionProvider(org.apache.jackrabbit.webdav.DavSessionProvider)
*/
public synchronized void setDavSessionProvider(DavSessionProvider sessionProvider) {
this.davSessionProvider = sessionProvider;
}
/**
* Returns the header value retrieved from the {@link #INIT_PARAM_AUTHENTICATE_HEADER}
* init parameter. If the parameter is missing, the value defaults to
* {@link #DEFAULT_AUTHENTICATE_HEADER}.
*
* @return the header value retrieved from the corresponding init parameter
* or {@link #DEFAULT_AUTHENTICATE_HEADER}.
* @see org.apache.jackrabbit.server.AbstractWebdavServlet#getAuthenticateHeaderValue()
*/
public String getAuthenticateHeaderValue() {
return authenticate_header;
}
/**
* Returns the resource configuration to be applied
*
* @return the resource configuration.
*/
public ResourceConfig getResourceConfig() {
// fallback if no config present
if (config == null) {
config = new ResourceConfig();
}
return config;
}
/**
* Set the resource configuration
*
* @param config
*/
public void setResourceConfig(ResourceConfig config) {
this.config = config;
}
/**
* Returns the <code>Repository</code>. If no repository has been set or
* created the repository initialized by <code>RepositoryAccessServlet</code>
* is returned.
*
* @return repository
* @see RepositoryAccessServlet#getRepository(ServletContext)
*/
public Repository getRepository() {
if (repository == null) {
repository = RepositoryAccessServlet.getRepository(getServletContext());
}
return repository;
}
/**
* Sets the <code>Repository</code>.
*
* @param repository
*/
public void setRepository(Repository repository) {
this.repository = repository;
}
}