optional EL support (only when Tiles EL module present); got rid of tiles-servlet-wildcard dependency (implemented wildcard support locally)

This commit is contained in:
Juergen Hoeller 2010-02-11 17:03:37 +00:00
parent 3db5a299bb
commit 16aa399040
2 changed files with 71 additions and 25 deletions

View File

@ -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<String, String> mergedInitParams;
private final ResourcePatternResolver resolver;
public SpringWildcardServletTilesApplicationContext(ServletContext servletContext, Map<String, String> params) {
super(servletContext);
this.mergedInitParams = new LinkedHashMap<String, String>();
@ -67,12 +77,36 @@ public class SpringTilesApplicationContextFactory extends AbstractTilesApplicati
if (params != null) {
this.mergedInitParams.putAll(params);
}
this.resolver = new ServletContextResourcePatternResolver(servletContext);
}
@Override
public Map<String, String> getInitParams() {
return this.mergedInitParams;
}
@Override
public URL getResource(String path) throws IOException {
URL retValue = null;
Set<URL> urlSet = getResources(path);
if (urlSet != null && !urlSet.isEmpty()) {
retValue = urlSet.iterator().next();
}
return retValue;
}
@Override
public Set<URL> getResources(String path) throws IOException {
Set<URL> urlSet = null;
Resource[] resources = this.resolver.getResources(path);
if (resources != null && resources.length > 0) {
urlSet = new HashSet<URL>();
for (Resource resource : resources) {
urlSet.add(resource.getURL());
}
}
return urlSet;
}
}
}

View File

@ -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
* <a href="http://tiles.apache.org">http://tiles.apache.org</a>
* for more information about Tiles, which basically is a templating
* mechanism for JSP-based web applications.
*
* <b>Note: Spring 3.0 requires Tiles 2.1.2 or above, with explicit support for Tiles 2.2.</b>
* Tiles 2.1's EL support will be activated by default when running on JSP 2.1 or above.
* Note that EL support is <i>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.
*
* <p>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<String, String>());
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<String, String>());
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);
}
}
}
}