/* vim: set ts=2 et sw=2 cindent fo=qroca: */ package com.globant.katari.core.web; import java.net.URL; import java.net.MalformedURLException; import javax.servlet.ServletContext; import javax.servlet.RequestDispatcher; import org.apache.commons.lang.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** A servlet context that wraps the web container servlet context. * * This servlet context makes the module unaware of the module container. It * changes the context path to include the url fragment where the module is * mapped. */ public final class ModuleServletContext extends ServletContextWrapper { /** The class logger. */ private static Logger log = LoggerFactory.getLogger( ModuleServletContext.class); /** The module container servlet. * * It is never null. */ private ModuleContainerServlet container; /** The servlet context to which most of the methods will delegate the * implementation. * * This is usually the web container provided servlet context. It is never * null. */ private ServletContext delegate; /** The module name. * * It is never null. */ private String moduleName; /** Builds a servlet context for a module. * * @param theContainer The servlet that acts as container for the modules. * The container knows how to dispatch requests to different modules. It * cannot be null. * * @param theDelegate The servlet context to which most of the methods will * delegate the implementation. It cannot be null. * * @param module The module name. It cannot be null. */ ModuleServletContext(final ModuleContainerServlet theContainer, final ServletContext theDelegate, final String module) { super(theDelegate); Validate.notNull(theContainer, "The container cannot be null"); Validate.notNull(theDelegate, "The delegate cannot be null"); Validate.notNull(module, "The module name cannot be null"); container = theContainer; delegate = theDelegate; moduleName = module; } /** Returns a RequestDispatcher object that acts as a wrapper for the * resource located at the given path. * * @param path The path to forward to or include. * * @return Returns a RequestDispatcher that can forward or include the given * path. */ public RequestDispatcher getRequestDispatcher(final String path) { if (log.isTraceEnabled()) { log.trace("Entering getRequestDispatcher('" + path + "')"); } // RequestDispatcher dispatcher = delegate.getRequestDispatcher(path); RequestDispatcher dispatcher; dispatcher = new ModuleRequestDispatcher(container, moduleName, path); log.trace("Leaving getRequestDispatcher"); return dispatcher; } /** Returns a URL to the resource that is mapped to a specified path. * * In this implementation, if the resource is not found relative to the * context, then it is search in the classloader that loaded the servlet. * * This is done to allow serlvet configurations like struts to be loaded from * the classpath. There was a portability problem between jetty and tomcat: * jetty could not find the struts configuration file if it's location * started with a slash. And without the leading slash, it did not work in * tomcat. * * TODO Decide if we should try the context class loader before the servlet * classloader. * * @param path Path of the content resource. * * @return Returns a URL object allowing access to any content resource * requested. * * @throws MalformedURLException if the resource path is not properly formed. */ public URL getResource(final String path) throws MalformedURLException { log.trace("Entering getResource('{}')", path); URL url = null; try { url = delegate.getResource(path); } catch (Exception e) { log.error("Not found in delegate", e); } if (url == null) { try { url = getClass().getResource(path); } catch (Exception e) { log.error("Not found in class loader", e); } } if (url == null) { try { url = getClass().getResource("/" + path); } catch (Exception e) { log.error("Not found in class loader with /", e); } } log.trace("Leaving getResource"); return url; } }