diff --git a/spring-faces/src/main/java/org/springframework/faces/config/ResourcesBeanDefinitionParser.java b/spring-faces/src/main/java/org/springframework/faces/config/ResourcesBeanDefinitionParser.java index f7e43915..b404b63b 100644 --- a/spring-faces/src/main/java/org/springframework/faces/config/ResourcesBeanDefinitionParser.java +++ b/spring-faces/src/main/java/org/springframework/faces/config/ResourcesBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008 the original author or authors. + * Copyright 2004-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.faces.config; import java.util.Map; @@ -22,6 +23,7 @@ import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.faces.webflow.JsfRuntimeInformation; import org.springframework.util.StringUtils; import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter; @@ -31,51 +33,98 @@ import org.w3c.dom.Element; * Parser for the resources tag. * * @author Rossen Stoyanchev + * @author Phillip Webb * @since 2.2.0 */ public class ResourcesBeanDefinitionParser implements BeanDefinitionParser { - static final String RESOURCE_HANDLER_BEAN_NAME = "jsfResourceRequestHandler"; - static final String RESOURCE_HANDLER_CLASS_NAME = "org.springframework.faces.webflow.JsfResourceRequestHandler"; + static final String SERVLET_RESOURCE_HANDLER_BEAN_NAME = "jsfResourceRequestHandler"; + + static final String PORTLET_RESOURCE_HANDLER_BEAN_NAME = "jsfPortletResourceRequestHandler"; public BeanDefinition parse(Element element, ParserContext parserContext) { - Object source = parserContext.extractSource(element); - registerHandlerAdapterIfNecessary(parserContext, source); - registerResourceHandler(parserContext, source); - registerHandlerMappings(element, parserContext, source); + new ServletRegistrar(element, parserContext).register(); + if (JsfRuntimeInformation.isSpringPortletPresent()) { + new PortletRegistrar(element, parserContext).register(); + } return null; } - private void registerHandlerMappings(Element element, ParserContext parserContext, Object source) { - Map urlMap = new ManagedMap(); - urlMap.put("/javax.faces.resource/**", RESOURCE_HANDLER_BEAN_NAME); + private static abstract class Registrar { - RootBeanDefinition beanDefinition = new RootBeanDefinition(SimpleUrlHandlerMapping.class); - beanDefinition.setSource(source); - beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - beanDefinition.getPropertyValues().add("urlMap", urlMap); + protected final Element element; - String order = element.getAttribute("order"); - beanDefinition.getPropertyValues().add("order", StringUtils.hasText(order) ? order : 0); - parserContext.getReaderContext().registerWithGeneratedName(beanDefinition); - } + protected final ParserContext parserContext; - private void registerResourceHandler(ParserContext parserContext, Object source) { - RootBeanDefinition beanDefinition = new RootBeanDefinition(RESOURCE_HANDLER_CLASS_NAME); - beanDefinition.setSource(source); - beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - parserContext.getRegistry().registerBeanDefinition(RESOURCE_HANDLER_BEAN_NAME, beanDefinition); - } + protected final Object source; - private void registerHandlerAdapterIfNecessary(ParserContext parserContext, Object source) { - if (parserContext.getRegistry().containsBeanDefinition( - "org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter")) { - return; + public Registrar(Element element, ParserContext parserContext) { + this.element = element; + this.parserContext = parserContext; + this.source = parserContext.extractSource(element); + } + + public abstract void register(); + } + + private static class ServletRegistrar extends Registrar { + + public ServletRegistrar(Element element, ParserContext parserContext) { + super(element, parserContext); + } + + @Override + public void register() { + registerHandlerAdapterIfNecessary(); + registerResourceHandler(); + registerHandlerMappings(); + } + + private void registerHandlerAdapterIfNecessary() { + if (parserContext.getRegistry().containsBeanDefinition("org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter")) { + return; + } + RootBeanDefinition beanDefinition = new RootBeanDefinition(HttpRequestHandlerAdapter.class); + beanDefinition.setSource(source); + beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + parserContext.getReaderContext().registerWithGeneratedName(beanDefinition); + } + + private void registerResourceHandler() { + RootBeanDefinition beanDefinition = new RootBeanDefinition("org.springframework.faces.webflow.JsfResourceRequestHandler"); + beanDefinition.setSource(source); + beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + parserContext.getRegistry().registerBeanDefinition(SERVLET_RESOURCE_HANDLER_BEAN_NAME, beanDefinition); + } + + private void registerHandlerMappings() { + Map urlMap = new ManagedMap(); + urlMap.put("/javax.faces.resource/**", SERVLET_RESOURCE_HANDLER_BEAN_NAME); + + RootBeanDefinition beanDefinition = new RootBeanDefinition(SimpleUrlHandlerMapping.class); + beanDefinition.setSource(source); + beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + beanDefinition.getPropertyValues().add("urlMap", urlMap); + + String order = element.getAttribute("order"); + beanDefinition.getPropertyValues().add("order", StringUtils.hasText(order) ? order : 0); + parserContext.getReaderContext().registerWithGeneratedName(beanDefinition); + } + } + + private static class PortletRegistrar extends Registrar { + + public PortletRegistrar(Element element, ParserContext parserContext) { + super(element, parserContext); + } + + @Override + public void register() { + RootBeanDefinition beanDefinition = new RootBeanDefinition("org.springframework.faces.webflow.context.portlet.JsfResourceRequestHandler"); + beanDefinition.setSource(source); + beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + parserContext.getRegistry().registerBeanDefinition(PORTLET_RESOURCE_HANDLER_BEAN_NAME, beanDefinition); } - RootBeanDefinition beanDefinition = new RootBeanDefinition(HttpRequestHandlerAdapter.class); - beanDefinition.setSource(source); - beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - parserContext.getReaderContext().registerWithGeneratedName(beanDefinition); } } \ No newline at end of file diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfRuntimeInformation.java b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfRuntimeInformation.java index 226b7639..0d86b1d4 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfRuntimeInformation.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfRuntimeInformation.java @@ -42,7 +42,13 @@ public class JsfRuntimeInformation { private static final int jsfVersion; - private static final boolean myFacesPresent = ClassUtils.isPresent("org.apache.myfaces.webapp.MyFacesServlet", JsfUtils.class.getClassLoader()); + private static final ClassLoader CLASS_LOADER = JsfUtils.class.getClassLoader(); + + private static final boolean myFacesPresent = ClassUtils.isPresent("org.apache.myfaces.webapp.MyFacesServlet", CLASS_LOADER); + + private static boolean portletPresent = ClassUtils.isPresent("javax.portlet.Portlet", CLASS_LOADER); + + private static boolean springPortletPresent = ClassUtils.isPresent("org.springframework.web.portlet.DispatcherPortlet", CLASS_LOADER); static { if (ReflectionUtils.findMethod(FacesContext.class, "isPostback") != null) { @@ -82,6 +88,15 @@ public class JsfRuntimeInformation { return myFacesPresent; } + /** + * Determines if the container has support for portlets and if Spring MVC portlet support is available + * + * @return true if a portlet environment is detected + */ + public static boolean isSpringPortletPresent() { + return portletPresent && springPortletPresent; + } + /** * Determine if the specified {@link FacesContext} is from a portlet request. * diff --git a/spring-faces/src/test/java/org/springframework/faces/config/ResourcesBeanDefinitionParserTests.java b/spring-faces/src/test/java/org/springframework/faces/config/ResourcesBeanDefinitionParserTests.java index 3df99759..5f1d9018 100644 --- a/spring-faces/src/test/java/org/springframework/faces/config/ResourcesBeanDefinitionParserTests.java +++ b/spring-faces/src/test/java/org/springframework/faces/config/ResourcesBeanDefinitionParserTests.java @@ -24,16 +24,21 @@ public class ResourcesBeanDefinitionParserTests extends TestCase { Map map = this.context.getBeansOfType(HttpRequestHandlerAdapter.class); assertEquals(1, map.values().size()); - Object resourceHandler = this.context.getBean(ResourcesBeanDefinitionParser.RESOURCE_HANDLER_BEAN_NAME); + Object resourceHandler = this.context.getBean(ResourcesBeanDefinitionParser.SERVLET_RESOURCE_HANDLER_BEAN_NAME); assertNotNull(resourceHandler); assertTrue(resourceHandler instanceof JsfResourceRequestHandler); map = this.context.getBeansOfType(SimpleUrlHandlerMapping.class); assertEquals(1, map.values().size()); SimpleUrlHandlerMapping handlerMapping = (SimpleUrlHandlerMapping) map.values().iterator().next(); - assertEquals(ResourcesBeanDefinitionParser.RESOURCE_HANDLER_BEAN_NAME, + assertEquals(ResourcesBeanDefinitionParser.SERVLET_RESOURCE_HANDLER_BEAN_NAME, handlerMapping.getUrlMap().get("/javax.faces.resource/**")); assertEquals(0, handlerMapping.getOrder()); } - + + public void testConfigurePortlet() { + Object resourceHandler = this.context.getBean(ResourcesBeanDefinitionParser.PORTLET_RESOURCE_HANDLER_BEAN_NAME); + assertNotNull(resourceHandler); + assertTrue(resourceHandler instanceof org.springframework.faces.webflow.context.portlet.JsfResourceRequestHandler); + } }