Java tutorial
/** ========================================================================= * * Copyright (C) 2012 IBM Corporation * * based on work of * * Copyright (C) 2006, 2007 TAO Consulting Pte <http://www.taoconsulting.sg/> * * All rights reserved. * * ========================================================================== * * * * 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 com.ibm.xsp.webdav; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.HashMap; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.ibm.xsp.webdav.methods.WebdavMethodFactory; import com.ibm.xsp.webdav.DAVCredentials; import biz.taoconsulting.dominodav.LockManager; import biz.taoconsulting.dominodav.interfaces.IDAVAddressInformation; import biz.taoconsulting.dominodav.interfaces.IDAVProcessable; import biz.taoconsulting.dominodav.interfaces.IDAVRepository; import biz.taoconsulting.dominodav.methods.Unimplemented; import com.ibm.xsp.webdav.repository.DAVRepositoryMETA; /** * webDAV files servlet * * @author Stephan H. Wissel */ public class WebDavServlet extends HttpServlet { private static final long serialVersionUID = 4L; private WebDavManager manager; private String servletPath; /** * The logger object for event logging */ private static final Log LOGGER = LogFactory.getLog(WebDavServlet.class); /** * @param servletPath * = The calling path of the servlet * @return Returns the lockManager - wrapper around webDavManager for * backwards compatibility */ public LockManager getLockManager() { return this.getManager().getLockManager(); } /** * Gets the webDavManager * * @return The webDAVManager */ private WebDavManager getManager() { if (this.manager == null) { this.manager = WebDavManager.getManager(servletPath); } return this.manager; } /** * Retrieves a method instance if one is configured and the current * repository does support it * * @param req * servlet request * @param resp * servlet response * @param repository * the repository to retrieve * @return the method instance */ private IDAVProcessable getMethod(HttpServletRequest req, HttpServletResponse resp, IDAVRepository repository) { // If we don't have a repository, we don't need a method if (repository == null) { return null; } // The final method instance IDAVProcessable meth = null; // Extract the Method name String curMethod = req.getMethod(); String repName = ((IDAVAddressInformation) repository).getName(); // LOGGER.info("Try to load HTTP Service: " + curMethod + " for " + // repName); if (repository.isSupportedMethod(curMethod)) { // Get the class and then the object String classForMethod = this.getManager().getClassForMethod(curMethod); if (classForMethod != null) { meth = WebdavMethodFactory.newInstance(curMethod, this.getManager()); if (meth != null) { // Store the context for mime retrieval meth.setContext(this.getServletContext()); } } } LOGGER.debug((meth == null) ? (curMethod + " could not be loaded for " + repName) : (curMethod + " sucessfully loaded for " + repName)); return meth; } /** * @param req * The HTTP Request * @param repositoryName * the repository to load * @return */ private IDAVRepository getRepository(HttpServletRequest req, String curPathFromServlet, String servletPath) { // The session where the Repository might be stored IDAVRepository result = null; DAVRepositoryMETA meta = null; String curRepositoryName = null; if (curPathFromServlet == null || curPathFromServlet.equals("/")) { curRepositoryName = "/"; // We make sure we have a legitimate value } else { // Find the name of the repository. First in the chain // [1] = second part since the path starts with / so [0] = "" // [1] = our value curRepositoryName = curPathFromServlet.split("/")[1]; } // The HTTP Session to cache repositories @SuppressWarnings("unused") HttpSession hs = req.getSession(); meta = this.getManager().getRepositoryMeta(); if (curRepositoryName.equals("/")) { result = meta; } else { // TODO: Is that a good idea to save the session, // hs.get/setAttribute commented out for now HashMap<String, IDAVRepository> sessionRepositories = null; // Object rlObject = null; // Object rlObject = hs.getAttribute("repositoryList"); // if (rlObject != null) { // sessionRepositories = (HashMap<String, IDAVRepository>) rlObject; // } else { sessionRepositories = new HashMap<String, IDAVRepository>(); // hs.setAttribute("repositoryList", sessionRepositories); // } if (sessionRepositories.containsKey(curRepositoryName)) { result = sessionRepositories.get(curRepositoryName); } else { result = meta.loadRepository(curRepositoryName); // sessionRepositories.put(curRepositoryName, result); } } return result; } /** * Resets the Manager, so it gets reloaded */ private void reset() { if (this.manager == null || this.manager.isAllowReset()) { this.manager = WebDavManager.getManager(this.servletPath, true); } } /** * (non-Javadoc) * * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override protected void service(HttpServletRequest req, HttpServletResponse resp) { boolean canContinue = true; // Optimistic String errorMessage = null; IDAVAddressInformation repoAddress = null; this.writeDefaultHeaderInfo(req, resp); // We need to extract the repository name from the requestURL // If that is empty we list the available repositories as directories String curPath = req.getPathInfo(); // LOGGER.info("Curr path="+curPath+"; method="+req.getMethod()); if (curPath != null) { try { curPath = URLDecoder.decode(curPath, "UTF-8"); } catch (UnsupportedEncodingException e1) { LOGGER.error(e1); curPath = req.getPathInfo(); // We take it unencoded then } } IDAVRepository repository = this.getRepository(req, curPath, servletPath); // LOGGER.info("CurrentPath="+curPath+"; servletPath="+servletPath+""); IDAVProcessable meth = this.getMethod(req, resp, repository); if (meth == null) { // LOGGER.info("Method is null"); } else { // LOGGER.info("Method is " +meth.getClass()); } // Now we could have everything, we check if we can move ahead // if ((repository == null) ||(curPath == null) || curPath.equals("/")){ if ((repository == null)) { // LOGGER.info("Not found"); resp.setStatus(HttpServletResponse.SC_NOT_FOUND); canContinue = false; errorMessage = "<HTML><HEAD><TITLE>Unable to Process Request</TITLE></HEAD><BODY><P>Http Status Code: 404</P><P>Reason: Unable to process request, resource not found</P></BODY></HTML>"; resp.setContentLength(errorMessage.length()); resp.setContentType("text/html"); try { PrintWriter out = resp.getWriter(); out.write(errorMessage); out.close(); return; } catch (IOException e) { LOGGER.error(e); } } else { // LOGGER.info("repository found "+repository.getClass()); repoAddress = (IDAVAddressInformation) repository; } // Without a method there's no point to continue if (canContinue && meth == null) { // LOGGER.info("Can continue and method is null"); resp.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED); canContinue = false; errorMessage = "<h1>Repository " + repoAddress.getName() + "</h1><h2>Sorry, but this repository doesn't support <span style=\"color : red; font-weight : bold;\">[HTTP " + req.getMethod() + "]</span></h2>"; } // Now update credentials if we have them if (repository != null) { this.updateCredentials(req, repository); } if (canContinue) { try { // LOGGER.info("Can continue...."); // We check if we can/have to reset the manager with all // repositories String reset = req.getParameter("reset"); if (reset != null) { this.reset(); } // Finally execute the method meth.process(req, resp, repository, this.getLockManager()); if (meth.getLastHttpStatus().equals(IDAVProcessable.NO_STATUS_SET) && meth.didMethodSucceed()) { resp.setStatus(HttpServletResponse.SC_OK); // Make sure we // have a status } else if (!meth.didMethodSucceed()) { canContinue = false; errorMessage = meth.getErrorMessage(); return; } } catch (IOException e) { resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); errorMessage = "<h1>Error executing " + meth.getClass().getName() + ": " + e.getMessage() + "</h1>"; canContinue = false; LOGGER.error(e); } } // We might have hit an error just above if (!canContinue) { // Write out the error Unimplemented nothingToDo = new Unimplemented(); nothingToDo.setUseStream(meth.streamUsed()); nothingToDo.setErrorMessage(errorMessage); nothingToDo.setErrNum(meth.getLastHttpStatus()); try { nothingToDo.process(req, resp, null, null); } catch (IOException e) { resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); LOGGER.error(e); } } } /** * Updates the repository with credentials, so the backend system can use * them (FileSystem / Domino / JDBC) * * @param req * @param repository */ private void updateCredentials(HttpServletRequest req, IDAVRepository repository) { // Update the repository with the credentials, so we can access // the backend properly, we retrieve the credentials from the // session HttpSession hs = req.getSession(); DAVCredentials cred; try { cred = (DAVCredentials) hs.getAttribute("credentials"); } catch (Exception e) { // Probably a typecast LOGGER.trace("Get credentials from session failed", e); cred = null; } if (cred == null) { cred = new DAVCredentials(); } cred.updateCredentials(req); repository.setCredentials(cred); // Save to the session hs.setAttribute("credentials", cred); } private void writeDefaultHeaderInfo(HttpServletRequest req, HttpServletResponse resp) { this.servletPath = req.getServletPath(); // LOGGER.info("req.getPathInfo():" + req.getPathInfo()); // LOGGER.info("req.getRequestURI():" + req.getRequestURI()); // LOGGER.info("req.getRequestURL():" + req.getRequestURL()); // LOGGER.info("req.getServletPath():" + this.servletPath); } }