/*
* Copyright 1999,2004 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.modeshape.web.jcr.webdav;
import java.io.File;
import java.io.IOException;
import javax.jcr.AccessDeniedException;
import javax.jcr.ItemExistsException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.LoginException;
import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.PathNotFoundException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.modeshape.common.logging.Logger;
import org.modeshape.webdav.IWebdavStore;
import org.modeshape.webdav.WebdavServlet;
import org.modeshape.webdav.exceptions.ObjectAlreadyExistsException;
import org.modeshape.webdav.exceptions.ObjectNotFoundException;
import org.modeshape.webdav.exceptions.WebdavException;
/**
* Custom servlet implementation that provides WebDAV access to a JCR repository. Nodes in the repository with a specified primary
* type (nt:file, by default) are treated as WebDAV resources (files) while nodes with any other primary type are treated as
* WebDAV folders.
*/
public class ModeShapeWebdavServlet extends WebdavServlet {
private static final long serialVersionUID = 1L;
public static final String INIT_CONTENT_MAPPER_CLASS_NAME = "org.modeshape.web.jcr.webdav.CONTENT_MAPPER_CLASS_NAME";
public static final String INIT_REQUEST_RESOLVER_CLASS_NAME = "org.modeshape.web.jcr.webdav.REQUEST_RESOLVER_CLASS_NAME";
private RequestResolver requestResolver;
private ContentMapper contentMapper;
@Override
protected IWebdavStore constructStore( String clazzName,
File root ) {
return new ModeShapeWebdavStore(requestResolver, contentMapper);
}
protected String getParam( String name ) {
return getServletContext().getInitParameter(name);
}
/**
* Loads and initializes the {@link #requestResolver}
*/
private void constructRequestResolver() {
// Initialize the request resolver
String requestResolverClassName = getParam(INIT_REQUEST_RESOLVER_CLASS_NAME);
Logger.getLogger(getClass()).debug("WebDAV Servlet resolver class name = " + requestResolverClassName);
if (requestResolverClassName == null) {
this.requestResolver = new MultiRepositoryRequestResolver();
} else {
try {
Class<? extends RequestResolver> clazz = Class.forName(requestResolverClassName).asSubclass(RequestResolver.class);
this.requestResolver = clazz.newInstance();
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
Logger.getLogger(getClass()).debug("WebDAV Servlet using resolver class = " + requestResolver.getClass().getName());
this.requestResolver.initialize(getServletContext());
}
/**
* Loads and initializes the {@link #contentMapper}
*/
private void constructContentMapper() {
// Initialize the request resolver
String contentMapperClassName = getParam(INIT_CONTENT_MAPPER_CLASS_NAME);
Logger.getLogger(getClass()).debug("WebDAV Servlet content mapper class name = " + contentMapperClassName);
if (contentMapperClassName == null) {
this.contentMapper = new DefaultContentMapper();
} else {
try {
Class<? extends ContentMapper> clazz = Class.forName(contentMapperClassName).asSubclass(ContentMapper.class);
this.contentMapper = clazz.newInstance();
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
Logger.getLogger(getClass()).debug("WebDAV Servlet using content mapper class = " + contentMapper.getClass().getName());
this.contentMapper.initialize(getServletContext());
}
@Override
public void init() throws ServletException {
constructRequestResolver();
constructContentMapper();
super.init();
}
/**
* <p>
* This method also sets and clears a thread-local reference to the incoming {@link HttpServletRequest request}.
* </p>
*/
@Override
protected void service( HttpServletRequest req,
HttpServletResponse resp ) throws ServletException, IOException {
ModeShapeWebdavStore.setRequest(req);
try {
super.service(req, resp);
} finally {
ModeShapeWebdavStore.setRequest(null);
}
}
@Override
protected Throwable translate( Throwable t ) {
return translateError(t);
}
protected static WebdavException translateError( Throwable t ) {
if (t instanceof AccessDeniedException) {
return new org.modeshape.webdav.exceptions.AccessDeniedException(t.getMessage(), t);
} else if (t instanceof LoginException) {
return new org.modeshape.webdav.exceptions.AccessDeniedException(t.getMessage(), t);
} else if (t instanceof ItemExistsException) {
return new ObjectAlreadyExistsException(t.getMessage(), t);
} else if (t instanceof PathNotFoundException) {
return new ObjectNotFoundException(t.getMessage(), t);
} else if (t instanceof ItemNotFoundException) {
return new ObjectNotFoundException(t.getMessage(), t);
} else if (t instanceof NoSuchWorkspaceException) {
return new ObjectNotFoundException(t.getMessage(), t);
} else {
return new WebdavException(t.getMessage(), t);
}
}
}