/* * $Header: /cvs/projects/easydoc-slide/src/webdav/server/org/apache/slide/webdav/WebdavServlet.java,v 1.2 2005/10/07 05:53:18 cruise Exp $ * $Revision: 1.2 $ * $Date: 2005/10/07 05:53:18 $ * * ==================================================================== * * Copyright 1999-2002 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.slide.webdav; import org.apache.slide.authenticate.SecurityToken; import org.apache.slide.common.Domain; import org.apache.slide.common.DomainInitializationFailedError; import org.apache.slide.common.NamespaceAccessToken; import org.apache.slide.util.logger.Logger; import org.apache.slide.webdav.util.DirectoryIndexGenerator; import org.apache.slide.webdav.util.WebdavUtils; import org.apache.slide.webdav.util.WebdavStatus; import javax.servlet.RequestDispatcher; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.UnavailableException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Date; /** * The WebDAV servlet. It is responsible for dispatching incoming requests to * implementations of the WebdavMethod interface. * * @version $Revision: 1.2 $ */ public class WebdavServlet extends HttpServlet { // -------------------------------------------------------------- Constants /** * Name of the log channel used by the WebDAV servlet. */ private static final String LOG_CHANNEL = WebdavServlet.class.getName(); /** * Name under which the namespace access token is stored in the application * attributes. This is used when the WebDAV servlet doesn't initialize * Slide itself, but rather the initialization is done outside. */ public static final String ATTRIBUTE_NAME = "org.apache.slide.NamespaceAccessToken"; // ----------------------------------------------------- Instance Variables /** * Access token to the namespace. */ protected NamespaceAccessToken token; /** * Directory browsing enabled. */ protected boolean directoryBrowsing = true; /** * RequestDispatcher to the directory browsing template, if specified. */ protected RequestDispatcher directoryBrowsingTemplate; /** * Directory browsing enabled. */ protected DirectoryIndexGenerator directoryIndexGenerator; /** * Set to true if the servlet is handling the lifecycle of the domain. */ protected boolean handleLifecycle = true; /** * Instance of the WebdavMethodFactory to use by this servlet. */ protected WebdavMethodFactory methodFactory; // -------------------------------------------------------- Servlet Methods protected void service (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { SimpleDateFormat sdf = new SimpleDateFormat(); if( token.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG) ) token.getLogger().log("==> "+req.getMethod()+" start: "+sdf.format(new Date(System.currentTimeMillis()))+" ["+Thread.currentThread().getName()+"]", LOG_CHANNEL, Logger.DEBUG); req.setAttribute("slide_uri", WebdavUtils.getRelativePath(req, (WebdavServletConfig) getServletConfig())); try { tryService(req, resp); } finally { if( token.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG) ) token.getLogger().log("<== "+req.getMethod()+" end: "+sdf.format(new Date(System.currentTimeMillis()))+" ["+Thread.currentThread().getName()+"]", LOG_CHANNEL, Logger.DEBUG); } } private void tryService(HttpServletRequest req, HttpServletResponse resp) { try { initContext(req); 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); } resp.setStatus(WebdavStatus.SC_OK); String methodName = req.getMethod(); WebdavMethod method = methodFactory.createMethod(methodName); if (method == null) { throw new WebdavException(WebdavStatus.SC_METHOD_NOT_ALLOWED); } else { method.run(req, resp); } } catch (WebdavException e) { // There has been an error somewhere ... token.getLogger().log(e, LOG_CHANNEL, Logger.ERROR); try { resp.sendError(e.getStatusCode()); } catch (Throwable ex) { } } catch (Throwable e) { // If something goes really wrong ... token.getLogger().log(e, LOG_CHANNEL, Logger.ERROR); try { resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR); } catch (Throwable ex) { } } finally { releaseContext(); } } protected void initContext(HttpServletRequest req) { } protected void releaseContext() { } /* private boolean isExtTx(HttpServletRequest req) { String hTxIdStr = req.getHeader(WebdavConstants.H_TRANSACTION); return (hTxIdStr != null); } private boolean isCollection(HttpServletRequest req) { SlideToken slideToken = new SlideTokenWrapper(WebdavUtils.getSlideToken(req)); // necessary as no transaction has been started, yet slideToken.setForceStoreEnlistment(false); slideToken.setForceSecurity(false); slideToken.setForceLock(false); return WebdavUtils.isCollection(token, slideToken, 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 (!isDomLevel2Parser()) { 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 value; // Lookup for the NAT using JNDI // FIXME // Lookup for the NAT using the servlet context token = (NamespaceAccessToken)getServletContext().getAttribute(ATTRIBUTE_NAME); if (token == null) { // Dafault initialization String namespaceName = null; String domainConfigFile = null; value = getInitParameter("namespace"); if (value != null) { namespaceName = value; } value = getInitParameter("domain"); if (value != null) { domainConfigFile = value; } try { if (domainConfigFile != null) { String rootPath = getServletContext().getRealPath("/"); Domain.setProperty("org.apache.slide.webapp.rootpath", rootPath); 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"); } getServletContext().setAttribute(ATTRIBUTE_NAME, token); } catch (DomainInitializationFailedError e) { log("Could not initialize domain", e); throw new UnavailableException(e.toString()); } catch (Throwable t) { t.printStackTrace(); throw new ServletException(t.toString()); } } else { handleLifecycle = false; } // Setup the method factory methodFactory = WebdavMethodFactory.newInstance((WebdavServletConfig)getServletConfig()); // Check whether directory browsing is enabled, and how it should be // accomplished // value = getInitParameter("directory-browsing"); // if (value != null) { // if (value.startsWith("/")) { // directoryBrowsingTemplate = // getServletContext().getRequestDispatcher(value); // if (directoryBrowsingTemplate == null) { // directoryBrowsing = false; // } // } else { // directoryBrowsing = Boolean.valueOf(value).booleanValue(); // } // } // if (directoryBrowsing) { // directoryIndexGenerator = // new DirectoryIndexGenerator // (token, (WebdavServletConfig)getServletConfig()); // } } /** * Destroy servlet. */ public void destroy() { if (handleLifecycle) { if (token != null) { Domain.closeNamespace(token); } } } // ------------------------------------------------------ Protected Methods /** * Handle a GET request on a collection resource. */ // protected void doGet(HttpServletRequest req, HttpServletResponse res) // throws ServletException, IOException { // // if (directoryBrowsing) { // if (directoryBrowsingTemplate != null) { // // attributes used by the tag library // req.setAttribute("org.apache.slide.NamespaceName", // token.getName()); // // attributes for general use // req.setAttribute("slide_namespace", token.getName()); // directoryBrowsingTemplate.forward(req, res); // } else { // try { // directoryIndexGenerator.generate(req, res); // } catch (AccessDeniedException e) { // res.sendError(WebdavStatus.SC_FORBIDDEN); // } catch (ObjectNotFoundException e) { // res.sendError(WebdavStatus.SC_NOT_FOUND); // } catch (LinkedObjectNotFoundException e) { // res.sendError(WebdavStatus.SC_NOT_FOUND); // } catch (SlideException e) { // res.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR); // } // } // } else { // res.sendError(WebdavStatus.SC_FORBIDDEN); // } // } static boolean isDomLevel2Parser() { try { return DocumentBuilderFactory.newInstance().newDocumentBuilder() .getDOMImplementation().hasFeature("Core", "2.0"); } catch (ParserConfigurationException e) { return false; } catch (FactoryConfigurationError e) { return false; } } }