diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/tiles2/SpringTilesApplicationContextFactory.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/tiles2/SpringTilesApplicationContextFactory.java index 3cb5cca3884..db630ce561b 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/tiles2/SpringTilesApplicationContextFactory.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/tiles2/SpringTilesApplicationContextFactory.java @@ -16,15 +16,23 @@ package org.springframework.web.servlet.view.tiles2; +import java.io.IOException; +import java.net.URL; import java.util.Enumeration; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; import javax.servlet.ServletContext; import org.apache.tiles.Initializable; import org.apache.tiles.TilesApplicationContext; import org.apache.tiles.context.AbstractTilesApplicationContextFactory; -import org.apache.tiles.servlet.context.wildcard.WildcardServletTilesApplicationContext; +import org.apache.tiles.servlet.context.ServletTilesApplicationContext; + +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.web.context.support.ServletContextResourcePatternResolver; /** * Spring-specific subclass of the standard Tiles AbstractTilesApplicationContextFactory, @@ -52,10 +60,12 @@ public class SpringTilesApplicationContextFactory extends AbstractTilesApplicati * Custom subclass of the standard Tiles WildcardServletTilesApplicationContext, * passing given properties through as Tiles init-param map. */ - private static class SpringWildcardServletTilesApplicationContext extends WildcardServletTilesApplicationContext { + private static class SpringWildcardServletTilesApplicationContext extends ServletTilesApplicationContext { private final Map mergedInitParams; + private final ResourcePatternResolver resolver; + public SpringWildcardServletTilesApplicationContext(ServletContext servletContext, Map params) { super(servletContext); this.mergedInitParams = new LinkedHashMap(); @@ -67,12 +77,36 @@ public class SpringTilesApplicationContextFactory extends AbstractTilesApplicati if (params != null) { this.mergedInitParams.putAll(params); } + this.resolver = new ServletContextResourcePatternResolver(servletContext); } @Override public Map getInitParams() { return this.mergedInitParams; } + + @Override + public URL getResource(String path) throws IOException { + URL retValue = null; + Set urlSet = getResources(path); + if (urlSet != null && !urlSet.isEmpty()) { + retValue = urlSet.iterator().next(); + } + return retValue; + } + + @Override + public Set getResources(String path) throws IOException { + Set urlSet = null; + Resource[] resources = this.resolver.getResources(path); + if (resources != null && resources.length > 0) { + urlSet = new HashSet(); + for (Resource resource : resources) { + urlSet.add(resource.getURL()); + } + } + return urlSet; + } } } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/tiles2/TilesConfigurer.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/tiles2/TilesConfigurer.java index 1c78181be57..a21c2bd6150 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/tiles2/TilesConfigurer.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/tiles2/TilesConfigurer.java @@ -62,14 +62,14 @@ import org.springframework.util.StringUtils; import org.springframework.web.context.ServletContextAware; /** - * Helper class to configure Tiles2 for the Spring Framework. See + * Helper class to configure Tiles 2.x for the Spring Framework. See * http://tiles.apache.org * for more information about Tiles, which basically is a templating * mechanism for JSP-based web applications. * * Note: Spring 3.0 requires Tiles 2.1.2 or above, with explicit support for Tiles 2.2. - * Tiles 2.1's EL support will be activated by default when running on JSP 2.1 or above. - * Note that EL support is not active by default when running against Tiles 2.2. + * Tiles 2.1's EL support will be activated by default when running on JSP 2.1 or above + * and when the Tiles EL module is present in the classpath. * *

The TilesConfigurer simply configures a TilesContainer using a set of files * containing definitions, to be accessed by {@link TilesView} instances. This is a @@ -103,8 +103,11 @@ import org.springframework.web.context.ServletContextAware; */ public class TilesConfigurer implements ServletContextAware, InitializingBean, DisposableBean { - private static final boolean jsp21Present = ClassUtils.isPresent( - "javax.servlet.jsp.JspApplicationContext", TilesConfigurer.class.getClassLoader()); + private static final boolean tilesElPresent = // requires JSP 2.1 as well as Tiles EL module + ClassUtils.isPresent( + "javax.servlet.jsp.JspApplicationContext", TilesConfigurer.class.getClassLoader()) && + ClassUtils.isPresent( + "org.apache.tiles.evaluator.el.ELAttributeEvaluator", TilesConfigurer.class.getClassLoader()); private static final boolean tiles22Present = ClassUtils.isPresent( "org.apache.tiles.evaluator.AttributeEvaluatorFactory", TilesConfigurer.class.getClassLoader()); @@ -140,8 +143,8 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D Boolean.toString(false)); this.tilesPropertyMap.put(DefinitionsFactory.LOCALE_RESOLVER_IMPL_PROPERTY, SpringLocaleResolver.class.getName()); - this.tilesPropertyMap.put(TilesContainerFactory.ATTRIBUTE_EVALUATOR_INIT_PARAM, - jsp21Present ? ELAttributeEvaluator.class.getName() : DirectAttributeEvaluator.class.getName()); + this.tilesPropertyMap.put(TilesContainerFactory.ATTRIBUTE_EVALUATOR_INIT_PARAM, tilesElPresent ? + "org.apache.tiles.evaluator.el.ELAttributeEvaluator" : DirectAttributeEvaluator.class.getName()); } @@ -308,25 +311,12 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D } } - if (jsp21Present && this.tilesInitializer instanceof SpringTilesInitializer) { + if (tilesElPresent && this.tilesInitializer instanceof SpringTilesInitializer) { // Again, we need to do this after initialization since SpringTilesContainerFactory // cannot override template methods that refer to Tiles 2.2 classes: in this case, // AttributeEvaluatorFactory as createAttributeEvaluatorFactory return type. - try { - BasicTilesContainer container = (BasicTilesContainer) ServletUtil.getContainer(this.servletContext); - Class aef = getClass().getClassLoader().loadClass("org.apache.tiles.evaluator.AttributeEvaluatorFactory"); - Class baef = getClass().getClassLoader().loadClass("org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory"); - Constructor baefCtor = baef.getConstructor(AttributeEvaluator.class); - ELAttributeEvaluator evaluator = new ELAttributeEvaluator(); - evaluator.setApplicationContext(container.getApplicationContext()); - evaluator.init(new HashMap()); - Object baefValue = baefCtor.newInstance(evaluator); - Method setter = container.getClass().getMethod("setAttributeEvaluatorFactory", aef); - setter.invoke(container, baefValue); - } - catch (Exception ex) { - throw new IllegalStateException("Cannot activate ELAttributeEvaluator", ex); - } + BasicTilesContainer container = (BasicTilesContainer) ServletUtil.getContainer(this.servletContext); + TilesElActivator.registerEvaluator(container); } } @@ -432,4 +422,26 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D } } + + private static class TilesElActivator { + + public static void registerEvaluator(BasicTilesContainer container) { + try { + ClassLoader cl = TilesElActivator.class.getClassLoader(); + Class aef = cl.loadClass("org.apache.tiles.evaluator.AttributeEvaluatorFactory"); + Class baef = cl.loadClass("org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory"); + Constructor baefCtor = baef.getConstructor(AttributeEvaluator.class); + ELAttributeEvaluator evaluator = new ELAttributeEvaluator(); + evaluator.setApplicationContext(container.getApplicationContext()); + evaluator.init(new HashMap()); + Object baefValue = baefCtor.newInstance(evaluator); + Method setter = container.getClass().getMethod("setAttributeEvaluatorFactory", aef); + setter.invoke(container, baefValue); + } + catch (Exception ex) { + throw new IllegalStateException("Cannot activate ELAttributeEvaluator", ex); + } + } + } + }