/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE and NOTICE files at the root of the source * tree and available online at * * http://www.dspace.org/license/ */ package org.dspace.springmvc; import org.apache.cocoon.servletservice.DynamicProxyRequestHandler; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.servlet.View; import javax.servlet.Servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; /** * @author Fabio Bolognesi (fabio at atmire dot com) * @author Mark Diggory (markd at atmire dot com) * @author Ben Bosman (ben at atmire dot com) */ public class CocoonView implements View { /** * The startup date of the Spring application context used to setup the {@link #blockServletCollector}. */ long applicationContextStartDate; /** * The servlet collector bean */ Map blockServletCollector; public CocoonView() { } void getInterfaces(Set interfaces, Class clazz) { Class[] clazzInterfaces = clazz.getInterfaces(); for (int i = 0; i < clazzInterfaces.length; i++) { //add all interfaces extended by this interface or directly //implemented by this class getInterfaces(interfaces, clazzInterfaces[i]); } // the superclazz is null if class is instanceof Object, is // an interface, a primitive type or void Class superclazz = clazz.getSuperclass(); if (superclazz != null) { //add all interfaces of the superclass to the list getInterfaces(interfaces, superclazz); } interfaces.addAll(Arrays.asList(clazzInterfaces)); } public String getContentType() { return null; } public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { final Map mountableServlets = getBlockServletMap(request); String path = request.getPathInfo(); if (path == null) { path = ""; } // find the servlet which mount path is the longest prefix of the path info int index = path.length(); Servlet servlet = null; while (servlet == null && index != -1) { path = path.substring(0, index); servlet = (Servlet) mountableServlets.get(path); index = path.lastIndexOf('/'); } //case when servlet is mounted at "/" must be handled separately servlet = servlet == null ? (Servlet) mountableServlets.get("/") : servlet; if (servlet == null) { String message = "No block for " + request.getPathInfo(); response.sendError(HttpServletResponse.SC_NOT_FOUND, message); return; } // Create a dynamic proxy class that overwrites the getServletPath and // getPathInfo methods to provide reasonable values in the called servlet // the dynamic proxy implements all interfaces of the original request HttpServletRequest prequest = (HttpServletRequest) Proxy.newProxyInstance( request.getClass().getClassLoader(), getInterfaces(request.getClass()), new DynamicProxyRequestHandler(request, path)); servlet.service(prequest, response); } Class[] getInterfaces(final Class clazz) { Set interfaces = new LinkedHashSet(); getInterfaces(interfaces, clazz); return (Class[]) interfaces.toArray(new Class[interfaces.size()]); } public Map getBlockServletMap(HttpServletRequest request) { ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession(true).getServletContext()); if (this.blockServletCollector == null || applicationContext.getStartupDate() != this.applicationContextStartDate) { this.applicationContextStartDate = applicationContext.getStartupDate(); this.blockServletCollector = (Map) applicationContext.getBean("org.apache.cocoon.servletservice.spring.BlockServletMap"); } return blockServletCollector; } }