Make Tiles 3 the default implementation in spring-webmvc

Move spring-webmvc-tiles3 content to spring-webmvc, and
create a spring-webmvc-tiles2 module with Tiles 2 support.

Its allows View Resolution to configure Tiles 3 instead of Tiles 2.

Issue: SPR-7093
This commit is contained in:
Sebastien Deleuze
2014-06-19 10:23:46 +02:00
committed by Rossen Stoyanchev
parent 92402e7715
commit a26b1ef8d9
33 changed files with 63 additions and 42 deletions

View File

@@ -16,9 +16,9 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import org.springframework.web.servlet.view.tiles2.TilesConfigurer;
import org.springframework.web.servlet.view.tiles2.TilesView;
import org.springframework.web.servlet.view.tiles2.TilesViewResolver;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesView;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
import org.w3c.dom.Element;
@@ -26,10 +26,10 @@ public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser {
private static final String INTERNAL_VIEW_RESOLVER_BEAN_NAME =
"org.springframework.web.servlet.view.InternalResourceViewResolver";
private static final String TILES2_VIEW_RESOLVER_BEAN_NAME =
"org.springframework.web.servlet.view.tiles2.TilesViewResolver";
private static final String TILES2_CONFIGURER_BEAN_NAME =
"org.springframework.web.servlet.view.tiles2.TilesConfigurer";
private static final String TILES3_VIEW_RESOLVER_BEAN_NAME =
"org.springframework.web.servlet.view.tiles3.TilesViewResolver";
private static final String TILES3_CONFIGURER_BEAN_NAME =
"org.springframework.web.servlet.view.tiles3.TilesConfigurer";
private static final String BEANNAME_VIEW_RESOLVER_BEAN_NAME =
"org.springframework.web.servlet.view.BeanNameViewResolver";
private static final String FREEMARKER_CONFIGURER_BEAN_NAME =
@@ -81,7 +81,7 @@ public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser {
}
private void registerBean(String beanName,Map<String,Object> propertyMap,Class beanClass ){
private void registerBean(String beanName,Map<String,Object> propertyMap,Class<?> beanClass ){
RootBeanDefinition beanDef = new RootBeanDefinition(beanClass);
beanDef.setSource(source);
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
@@ -125,20 +125,20 @@ public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser {
}
private void registerTilesConfigurerBean(ParserContext parserContext,Element viewResolverElement) {
if (!parserContext.getRegistry().containsBeanDefinition(TILES2_CONFIGURER_BEAN_NAME)) {
if (!parserContext.getRegistry().containsBeanDefinition(TILES3_CONFIGURER_BEAN_NAME)) {
Map<String, Object> propertyMap= new HashMap<String, Object>();
propertyMap.put("definitions", viewResolverElement.getAttribute("definitions"));
registerBean(TILES2_CONFIGURER_BEAN_NAME, propertyMap, TilesConfigurer.class);
registerBean(TILES3_CONFIGURER_BEAN_NAME, propertyMap, TilesConfigurer.class);
}
}
private void registerTilesViewResolverBean(ParserContext parserContext, Element viewResolverElement) {
if (!parserContext.getRegistry().containsBeanDefinition(TILES2_VIEW_RESOLVER_BEAN_NAME)) {
if (!parserContext.getRegistry().containsBeanDefinition(TILES3_VIEW_RESOLVER_BEAN_NAME)) {
Map<String, Object> propertyMap= new HashMap<String, Object>();
propertyMap.put("viewClass", TilesView.class);
propertyMap.put("order", 1);
registerBean(TILES2_VIEW_RESOLVER_BEAN_NAME, propertyMap, TilesViewResolver.class);
registerBean(TILES3_VIEW_RESOLVER_BEAN_NAME, propertyMap, TilesViewResolver.class);
}
}
private void registerInternalResourceViewResolverBean(ParserContext parserContext, Element viewResolverElement) {

View File

@@ -1,60 +0,0 @@
/*
* Copyright 2002-2009 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles2;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.PageContext;
import org.apache.tiles.context.TilesRequestContext;
import org.apache.tiles.jsp.context.JspTilesRequestContext;
import org.apache.tiles.locale.impl.DefaultLocaleResolver;
import org.apache.tiles.servlet.context.ServletTilesRequestContext;
import org.springframework.web.servlet.support.RequestContextUtils;
/**
* Tiles LocaleResolver adapter that delegates to a Spring
* {@link org.springframework.web.servlet.LocaleResolver},
* exposing the DispatcherServlet-managed locale.
*
* <p>This adapter gets automatically registered by {@link TilesConfigurer}.
* If you are using standard Tiles bootstrap, specify the name of this class
* as value for the init-param "org.apache.tiles.locale.LocaleResolver".
*
* @author Juergen Hoeller
* @since 2.5
* @see org.apache.tiles.definition.UrlDefinitionsFactory#LOCALE_RESOLVER_IMPL_PROPERTY
*/
public class SpringLocaleResolver extends DefaultLocaleResolver {
@Override
public Locale resolveLocale(TilesRequestContext context) {
if (context instanceof JspTilesRequestContext) {
PageContext pc = ((JspTilesRequestContext) context).getPageContext();
return RequestContextUtils.getLocale((HttpServletRequest) pc.getRequest());
}
else if (context instanceof ServletTilesRequestContext) {
HttpServletRequest request = ((ServletTilesRequestContext) context).getRequest();
if (request != null) {
return RequestContextUtils.getLocale(request);
}
}
return super.resolveLocale(context);
}
}

View File

@@ -1,71 +0,0 @@
/*
* Copyright 2002-2014 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles2;
import java.io.IOException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.ServletContext;
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 Tiles ServletTilesApplicationContext.
*
* @author Juergen Hoeller
* @since 4.0.1
*/
public class SpringWildcardServletTilesApplicationContext extends ServletTilesApplicationContext {
private final ResourcePatternResolver resolver;
public SpringWildcardServletTilesApplicationContext(ServletContext servletContext) {
super(servletContext);
this.resolver = new ServletContextResourcePatternResolver(servletContext);
}
@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

@@ -1,91 +0,0 @@
/*
* Copyright 2002-2013 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles2;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.tiles.TilesApplicationContext;
import org.apache.tiles.TilesContainer;
import org.apache.tiles.context.TilesRequestContext;
import org.apache.tiles.impl.BasicTilesContainer;
import org.apache.tiles.servlet.context.ServletTilesApplicationContext;
import org.apache.tiles.servlet.context.ServletTilesRequestContext;
import org.apache.tiles.servlet.context.ServletUtil;
import org.springframework.web.servlet.support.JstlUtils;
import org.springframework.web.servlet.support.RequestContext;
import org.springframework.web.servlet.view.AbstractUrlBasedView;
/**
* {@link org.springframework.web.servlet.View} implementation that retrieves a
* Tiles definition. The "url" property is interpreted as name of a Tiles definition.
*
* <p>This class builds on Tiles2, which requires JSP 2.0.
* JSTL support is integrated out of the box due to JSTL's inclusion in JSP 2.0.
* <b>Note: Spring 4.0 requires Tiles 2.2.2.</b>
*
* <p>Depends on a TilesContainer which must be available in
* the ServletContext. This container is typically set up via a
* {@link TilesConfigurer} bean definition in the application context.
*
* @author Juergen Hoeller
* @since 2.5
* @see #setUrl
* @see TilesConfigurer
*/
public class TilesView extends AbstractUrlBasedView {
@Override
public boolean checkResource(final Locale locale) throws Exception {
TilesContainer container = ServletUtil.getContainer(getServletContext());
if (!(container instanceof BasicTilesContainer)) {
// Cannot check properly - let's assume it's there.
return true;
}
BasicTilesContainer basicContainer = (BasicTilesContainer) container;
TilesApplicationContext appContext = new ServletTilesApplicationContext(getServletContext());
TilesRequestContext requestContext = new ServletTilesRequestContext(appContext, null, null) {
@Override
public Locale getRequestLocale() {
return locale;
}
};
return (basicContainer.getDefinitionsFactory().getDefinition(getUrl(), requestContext) != null);
}
@Override
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
ServletContext servletContext = getServletContext();
TilesContainer container = ServletUtil.getContainer(servletContext);
if (container == null) {
throw new ServletException("Tiles container is not initialized. " +
"Have you added a TilesConfigurer to your web application context?");
}
exposeModelAsRequestAttributes(model, request);
JstlUtils.exposeLocalizationContext(new RequestContext(request, servletContext));
container.render(getUrl(), request, response);
}
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright 2002-2009 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles2;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
/**
* Convenience subclass of {@link org.springframework.web.servlet.view.UrlBasedViewResolver}
* that supports {@link TilesView} (i.e. Tiles definitions) and custom subclasses of it.
*
* <p>The view class for all views generated by this resolver can be specified
* via the "viewClass" property. See UrlBasedViewResolver's javadoc for details.
*
* <p><b>Note:</b> When chaining ViewResolvers, a TilesViewResolver will
* check for the existence of the specified template resources and only return
* a non-null View object if the template was actually found.
*
* @author Juergen Hoeller
* @since 3.0
* @see #setViewClass
* @see #setPrefix
* @see #setSuffix
* @see #setRequestContextAttribute
* @see TilesView
*/
public class TilesViewResolver extends UrlBasedViewResolver {
public TilesViewResolver() {
setViewClass(requiredViewClass());
}
/**
* Requires {@link TilesView}.
*/
@Override
protected Class<?> requiredViewClass() {
return TilesView.class;
}
}

View File

@@ -14,22 +14,22 @@
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles2;
package org.springframework.web.servlet.view.tiles3;
import org.apache.tiles.TilesException;
import org.apache.tiles.context.TilesRequestContext;
import org.apache.tiles.preparer.PreparerFactory;
import org.apache.tiles.preparer.ViewPreparer;
import org.apache.tiles.preparer.factory.PreparerFactory;
import org.apache.tiles.request.Request;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
/**
* Abstract implementation of the Tiles2 {@link org.apache.tiles.preparer.PreparerFactory}
* Abstract implementation of the Tiles3 {@link org.apache.tiles.preparer.PreparerFactory}
* interface, obtaining the current Spring WebApplicationContext and delegating to
* {@link #getPreparer(String, org.springframework.web.context.WebApplicationContext)}.
*
* @author Juergen Hoeller
* @since 2.5
* @since 3.2
* @see #getPreparer(String, org.springframework.web.context.WebApplicationContext)
* @see SimpleSpringPreparerFactory
* @see SpringBeanPreparerFactory
@@ -37,11 +37,11 @@ import org.springframework.web.servlet.DispatcherServlet;
public abstract class AbstractSpringPreparerFactory implements PreparerFactory {
@Override
public ViewPreparer getPreparer(String name, TilesRequestContext context) throws TilesException {
WebApplicationContext webApplicationContext = (WebApplicationContext) context.getRequestScope().get(
public ViewPreparer getPreparer(String name, Request context) {
WebApplicationContext webApplicationContext = (WebApplicationContext) context.getContext("request").get(
DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (webApplicationContext == null) {
webApplicationContext = (WebApplicationContext) context.getApplicationContext().getApplicationScope().get(
webApplicationContext = (WebApplicationContext) context.getContext("application").get(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (webApplicationContext == null) {
throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");

View File

@@ -14,26 +14,25 @@
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles2;
package org.springframework.web.servlet.view.tiles3;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.tiles.TilesException;
import org.apache.tiles.preparer.NoSuchPreparerException;
import org.apache.tiles.preparer.PreparerException;
import org.apache.tiles.preparer.ViewPreparer;
import org.apache.tiles.preparer.factory.NoSuchPreparerException;
import org.springframework.web.context.WebApplicationContext;
/**
* Tiles2 {@link org.apache.tiles.preparer.PreparerFactory} implementation
* Tiles3 {@link org.apache.tiles.preparer.PreparerFactory} implementation
* that expects preparer class names and builds preparer instances for those,
* creating them through the Spring ApplicationContext in order to apply
* Spring container callbacks and configured Spring BeanPostProcessors.
*
* @author Juergen Hoeller
* @since 2.5
* @since 3.2
* @see SpringBeanPreparerFactory
*/
public class SimpleSpringPreparerFactory extends AbstractSpringPreparerFactory {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles2;
package org.springframework.web.servlet.view.tiles3;
import org.apache.tiles.TilesException;
import org.apache.tiles.preparer.ViewPreparer;
@@ -22,14 +22,14 @@ import org.apache.tiles.preparer.ViewPreparer;
import org.springframework.web.context.WebApplicationContext;
/**
* Tiles2 {@link org.apache.tiles.preparer.PreparerFactory} implementation
* Tiles3 {@link org.apache.tiles.preparer.PreparerFactory} implementation
* that expects preparer bean names and obtains preparer beans from the
* Spring ApplicationContext. The full bean creation process will be in
* the control of the Spring application context in this case, allowing
* for the use of scoped beans etc.
*
* @author Juergen Hoeller
* @since 2.5
* @since 3.2
* @see SimpleSpringPreparerFactory
*/
public class SpringBeanPreparerFactory extends AbstractSpringPreparerFactory {

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2002-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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles3;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import org.apache.tiles.locale.impl.DefaultLocaleResolver;
import org.apache.tiles.request.Request;
import org.apache.tiles.request.servlet.NotAServletEnvironmentException;
import org.apache.tiles.request.servlet.ServletUtil;
import org.springframework.web.servlet.support.RequestContextUtils;
/**
* Tiles LocaleResolver adapter that delegates to a Spring
* {@link org.springframework.web.servlet.LocaleResolver}, exposing the
* DispatcherServlet-managed locale.
*
* <p>This adapter gets automatically registered by {@link TilesConfigurer}.
*
* @author Nicolas Le Bas
* @since 3.2
* @see org.apache.tiles.definition.UrlDefinitionsFactory#LOCALE_RESOLVER_IMPL_PROPERTY
*/
public class SpringLocaleResolver extends DefaultLocaleResolver {
@Override
public Locale resolveLocale(Request request) {
try {
HttpServletRequest servletRequest = ServletUtil.getServletRequest(request).getRequest();
if (servletRequest != null) {
return RequestContextUtils.getLocale(servletRequest);
}
}
catch (NotAServletEnvironmentException e) {
// Ignore
}
return super.resolveLocale(request);
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2002-2013 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles3;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import javax.servlet.ServletContext;
import org.apache.tiles.request.ApplicationResource;
import org.apache.tiles.request.locale.URLApplicationResource;
import org.apache.tiles.request.servlet.ServletApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.support.ServletContextResourcePatternResolver;
/**
* Spring-specific subclass of the Tiles ServletApplicationContext.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class SpringWildcardServletTilesApplicationContext extends ServletApplicationContext {
private final ResourcePatternResolver resolver;
public SpringWildcardServletTilesApplicationContext(ServletContext servletContext) {
super(servletContext);
this.resolver = new ServletContextResourcePatternResolver(servletContext);
}
@Override
public ApplicationResource getResource(String localePath) {
ApplicationResource retValue = null;
Collection<ApplicationResource> urlSet = getResources(localePath);
if (urlSet != null && !urlSet.isEmpty()) {
retValue = urlSet.iterator().next();
}
return retValue;
}
@Override
public ApplicationResource getResource(ApplicationResource base, Locale locale) {
ApplicationResource retValue = null;
Collection<ApplicationResource> urlSet = getResources(base.getLocalePath(locale));
if (urlSet != null && !urlSet.isEmpty()) {
retValue = urlSet.iterator().next();
}
return retValue;
}
@Override
public Collection<ApplicationResource> getResources(String path) {
Resource[] resources;
try {
resources = this.resolver.getResources(path);
}
catch (IOException ex) {
return Collections.<ApplicationResource> emptyList();
}
Collection<ApplicationResource> resourceList = new ArrayList<ApplicationResource>();
if (!ObjectUtils.isEmpty(resources)) {
for (Resource resource : resources) {
URL url;
try {
url = resource.getURL();
resourceList.add(new URLApplicationResource(url.toExternalForm(), url));
}
catch (IOException ex) {
// shouldn't happen with the kind of resources we're using
throw new IllegalArgumentException("No URL for " + resource.toString(), ex);
}
}
}
return resourceList;
}
}

View File

@@ -14,32 +14,32 @@
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles2;
package org.springframework.web.servlet.view.tiles3;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.el.ArrayELResolver;
import javax.el.BeanELResolver;
import javax.el.CompositeELResolver;
import javax.el.ListELResolver;
import javax.el.MapELResolver;
import javax.el.ResourceBundleELResolver;
import javax.servlet.ServletContext;
import javax.servlet.jsp.JspFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tiles.TilesApplicationContext;
import org.apache.tiles.TilesContainer;
import org.apache.tiles.TilesException;
import org.apache.tiles.awareness.TilesApplicationContextAware;
import org.apache.tiles.context.TilesRequestContextFactory;
import org.apache.tiles.definition.DefinitionsFactory;
import org.apache.tiles.definition.DefinitionsFactoryException;
import org.apache.tiles.definition.DefinitionsReader;
import org.apache.tiles.definition.Refreshable;
import org.apache.tiles.definition.dao.BaseLocaleUrlDefinitionDAO;
import org.apache.tiles.definition.dao.CachingLocaleUrlDefinitionDAO;
import org.apache.tiles.definition.digester.DigesterDefinitionsReader;
import org.apache.tiles.el.ELAttributeEvaluator;
import org.apache.tiles.el.ScopeELResolver;
import org.apache.tiles.el.TilesContextBeanELResolver;
import org.apache.tiles.el.TilesContextELResolver;
import org.apache.tiles.evaluator.AttributeEvaluator;
import org.apache.tiles.evaluator.AttributeEvaluatorFactory;
import org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory;
@@ -48,11 +48,13 @@ import org.apache.tiles.extras.complete.CompleteAutoloadTilesContainerFactory;
import org.apache.tiles.extras.complete.CompleteAutoloadTilesInitializer;
import org.apache.tiles.factory.AbstractTilesContainerFactory;
import org.apache.tiles.factory.BasicTilesContainerFactory;
import org.apache.tiles.impl.BasicTilesContainer;
import org.apache.tiles.impl.mgmt.CachingTilesContainer;
import org.apache.tiles.locale.LocaleResolver;
import org.apache.tiles.preparer.PreparerFactory;
import org.apache.tiles.startup.AbstractTilesInitializer;
import org.apache.tiles.preparer.factory.PreparerFactory;
import org.apache.tiles.request.ApplicationContext;
import org.apache.tiles.request.ApplicationContextAware;
import org.apache.tiles.request.ApplicationResource;
import org.apache.tiles.startup.DefaultTilesInitializer;
import org.apache.tiles.startup.TilesInitializer;
import org.springframework.beans.BeanUtils;
@@ -64,14 +66,11 @@ import org.springframework.util.ClassUtils;
import org.springframework.web.context.ServletContextAware;
/**
* Helper class to configure Tiles 2.x for the Spring Framework. See
* Helper class to configure Tiles 3.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 web applications using JSPs and other template engines.
*
* <b>Note: Spring 4.0 requires Tiles 2.2.2.</b> Tiles' EL support will
* be activated by default 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
* Spring-based alternative (for usage in Spring configuration) to the Tiles-provided
@@ -85,7 +84,7 @@ import org.springframework.web.context.ServletContextAware;
* <p>A typical TilesConfigurer bean definition looks as follows:
*
* <pre class="code">
* &lt;bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
* &lt;bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
* &lt;property name="definitions">
* &lt;list>
* &lt;value>/WEB-INF/defs/general.xml&lt;/value>
@@ -101,8 +100,24 @@ import org.springframework.web.context.ServletContextAware;
* The values in the list are the actual Tiles XML files containing the definitions.
* If the list is not specified, the default is {@code "/WEB-INF/tiles.xml"}.
*
* <p>Note that in Tiles 3 an underscore in the name of a file containing Tiles
* definitions is used to indicate locale information, for example:
*
* <pre class="code">
* &lt;bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
* &lt;property name="definitions">
* &lt;list>
* &lt;value>/WEB-INF/defs/tiles.xml&lt;/value>
* &lt;value>/WEB-INF/defs/tiles_fr_FR.xml&lt;/value>
* &lt;/list>
* &lt;/property>
* &lt;/bean>
* </pre>
*
* @author mick semb wever
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 2.5
* @since 3.2
* @see TilesView
* @see TilesViewResolver
*/
@@ -144,7 +159,7 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
}
/**
* Specify whether to apply Tiles 2.2's "complete-autoload" configuration.
* Specify whether to apply Tiles 3.0's "complete-autoload" configuration.
* <p>See {@link org.apache.tiles.extras.complete.CompleteAutoloadTilesContainerFactory}
* for details on the complete-autoload mode.
* <p><b>NOTE: Specifying the complete-autoload mode effectively disables all other bean
@@ -159,7 +174,7 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
this.tilesInitializer = new SpringCompleteAutoloadTilesInitializer();
}
catch (Throwable ex) {
throw new IllegalStateException("Tiles-Extras 2.2 not available", ex);
throw new IllegalStateException("Tiles-Extras 3.0 not available", ex);
}
}
else {
@@ -204,8 +219,8 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
}
/**
* Set the {@link org.apache.tiles.preparer.PreparerFactory} implementation to use.
* Default is {@link org.apache.tiles.preparer.BasicPreparerFactory}, creating
* Set the {@link org.apache.tiles.preparer.factory.PreparerFactory} implementation to use.
* Default is {@link org.apache.tiles.preparer.factory.BasicPreparerFactory}, creating
* shared instances for specified preparer classes.
* <p>Specify {@link SimpleSpringPreparerFactory} to autowire
* {@link org.apache.tiles.preparer.ViewPreparer} instances based on specified
@@ -248,23 +263,13 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
*/
@Override
public void afterPropertiesSet() throws TilesException {
TilesApplicationContext preliminaryContext =
new SpringWildcardServletTilesApplicationContext(this.servletContext);
ApplicationContext preliminaryContext = new SpringWildcardServletTilesApplicationContext(this.servletContext);
if (this.tilesInitializer == null) {
this.tilesInitializer = createTilesInitializer();
this.tilesInitializer = new SpringTilesInitializer();
}
this.tilesInitializer.initialize(preliminaryContext);
}
/**
* Creates a new instance of {@link SpringTilesInitializer}.
* <p>Override it to use a different initializer.
* @see org.apache.tiles.web.startup.AbstractTilesListener#createTilesInitializer()
*/
protected TilesInitializer createTilesInitializer() {
return new SpringTilesInitializer();
}
/**
* Removes the TilesContainer from this web application.
* @throws TilesException in case of cleanup failure
@@ -275,10 +280,10 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
}
private class SpringTilesInitializer extends AbstractTilesInitializer {
private class SpringTilesInitializer extends DefaultTilesInitializer {
@Override
protected AbstractTilesContainerFactory createContainerFactory(TilesApplicationContext context) {
protected AbstractTilesContainerFactory createContainerFactory(ApplicationContext context) {
return new SpringTilesContainerFactory();
}
}
@@ -287,44 +292,29 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
private class SpringTilesContainerFactory extends BasicTilesContainerFactory {
@Override
protected BasicTilesContainer instantiateContainer(TilesApplicationContext context) {
return (useMutableTilesContainer ? new CachingTilesContainer() : new BasicTilesContainer());
public TilesContainer createContainer(ApplicationContext context) {
TilesContainer container = super.createContainer(context);
return (useMutableTilesContainer ? new CachingTilesContainer(container) : container);
}
@Override
protected void registerRequestContextFactory(String className,
List<TilesRequestContextFactory> factories, TilesRequestContextFactory parent) {
// Avoid Tiles 2.2 warn logging when default RequestContextFactory impl class not found
if (ClassUtils.isPresent(className, TilesConfigurer.class.getClassLoader())) {
super.registerRequestContextFactory(className, factories, parent);
}
}
@Override
protected List<URL> getSourceURLs(TilesApplicationContext applicationContext,
TilesRequestContextFactory contextFactory) {
protected List<ApplicationResource> getSources(ApplicationContext applicationContext) {
if (definitions != null) {
try {
List<URL> result = new LinkedList<URL>();
for (String definition : definitions) {
result.addAll(applicationContext.getResources(definition));
}
return result;
}
catch (IOException ex) {
throw new DefinitionsFactoryException("Cannot load definition URLs", ex);
List<ApplicationResource> result = new LinkedList<ApplicationResource>();
for (String definition : definitions) {
result.addAll(applicationContext.getResources(definition));
}
return result;
}
else {
return super.getSourceURLs(applicationContext, contextFactory);
return super.getSources(applicationContext);
}
}
@Override
protected BaseLocaleUrlDefinitionDAO instantiateLocaleDefinitionDao(TilesApplicationContext applicationContext,
TilesRequestContextFactory contextFactory, LocaleResolver resolver) {
BaseLocaleUrlDefinitionDAO dao = super.instantiateLocaleDefinitionDao(
applicationContext, contextFactory, resolver);
protected BaseLocaleUrlDefinitionDAO instantiateLocaleDefinitionDao(ApplicationContext applicationContext,
LocaleResolver resolver) {
BaseLocaleUrlDefinitionDAO dao = super.instantiateLocaleDefinitionDao(applicationContext, resolver);
if (checkRefresh && dao instanceof CachingLocaleUrlDefinitionDAO) {
((CachingLocaleUrlDefinitionDAO) dao).setCheckRefresh(true);
}
@@ -332,66 +322,56 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
}
@Override
protected DefinitionsReader createDefinitionsReader(TilesApplicationContext applicationContext,
TilesRequestContextFactory contextFactory) {
DigesterDefinitionsReader reader = new DigesterDefinitionsReader();
if (!validateDefinitions){
Map<String,String> map = new HashMap<String,String>();
map.put(DigesterDefinitionsReader.PARSER_VALIDATE_PARAMETER_NAME, Boolean.FALSE.toString());
reader.init(map);
}
protected DefinitionsReader createDefinitionsReader(ApplicationContext context) {
DigesterDefinitionsReader reader = (DigesterDefinitionsReader) super.createDefinitionsReader(context);
reader.setValidating(validateDefinitions);
return reader;
}
@Override
protected DefinitionsFactory createDefinitionsFactory(TilesApplicationContext applicationContext,
TilesRequestContextFactory contextFactory, LocaleResolver resolver) {
protected DefinitionsFactory createDefinitionsFactory(ApplicationContext applicationContext,
LocaleResolver resolver) {
if (definitionsFactoryClass != null) {
DefinitionsFactory factory = BeanUtils.instantiate(definitionsFactoryClass);
if (factory instanceof TilesApplicationContextAware) {
((TilesApplicationContextAware) factory).setApplicationContext(applicationContext);
if (factory instanceof ApplicationContextAware) {
((ApplicationContextAware) factory).setApplicationContext(applicationContext);
}
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(factory);
if (bw.isWritableProperty("localeResolver")) {
bw.setPropertyValue("localeResolver", resolver);
}
if (bw.isWritableProperty("definitionDAO")) {
bw.setPropertyValue("definitionDAO",
createLocaleDefinitionDao(applicationContext, contextFactory, resolver));
}
if (factory instanceof Refreshable) {
((Refreshable) factory).refresh();
bw.setPropertyValue("definitionDAO", createLocaleDefinitionDao(applicationContext, resolver));
}
return factory;
}
else {
return super.createDefinitionsFactory(applicationContext, contextFactory, resolver);
return super.createDefinitionsFactory(applicationContext, resolver);
}
}
@Override
protected PreparerFactory createPreparerFactory(TilesApplicationContext applicationContext,
TilesRequestContextFactory contextFactory) {
protected PreparerFactory createPreparerFactory(ApplicationContext context) {
if (preparerFactoryClass != null) {
return BeanUtils.instantiate(preparerFactoryClass);
}
else {
return super.createPreparerFactory(applicationContext, contextFactory);
return super.createPreparerFactory(context);
}
}
@Override
protected LocaleResolver createLocaleResolver(TilesApplicationContext applicationContext,
TilesRequestContextFactory contextFactory) {
protected LocaleResolver createLocaleResolver(ApplicationContext context) {
return new SpringLocaleResolver();
}
@Override
protected AttributeEvaluatorFactory createAttributeEvaluatorFactory(TilesApplicationContext applicationContext,
TilesRequestContextFactory contextFactory, LocaleResolver resolver) {
protected AttributeEvaluatorFactory createAttributeEvaluatorFactory(ApplicationContext context,
LocaleResolver resolver) {
AttributeEvaluator evaluator;
if (tilesElPresent && JspFactory.getDefaultFactory() != null) {
evaluator = TilesElActivator.createEvaluator(applicationContext);
evaluator = new TilesElActivator().createEvaluator();
}
else {
evaluator = new DirectAttributeEvaluator();
@@ -404,7 +384,7 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
private static class SpringCompleteAutoloadTilesInitializer extends CompleteAutoloadTilesInitializer {
@Override
protected AbstractTilesContainerFactory createContainerFactory(TilesApplicationContext context) {
protected AbstractTilesContainerFactory createContainerFactory(ApplicationContext context) {
return new SpringCompleteAutoloadTilesContainerFactory();
}
}
@@ -413,21 +393,36 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D
private static class SpringCompleteAutoloadTilesContainerFactory extends CompleteAutoloadTilesContainerFactory {
@Override
protected LocaleResolver createLocaleResolver(TilesApplicationContext applicationContext,
TilesRequestContextFactory contextFactory) {
protected LocaleResolver createLocaleResolver(ApplicationContext applicationContext) {
return new SpringLocaleResolver();
}
}
private static class TilesElActivator {
private class TilesElActivator {
public static AttributeEvaluator createEvaluator(TilesApplicationContext applicationContext) {
public AttributeEvaluator createEvaluator() {
ELAttributeEvaluator evaluator = new ELAttributeEvaluator();
evaluator.setApplicationContext(applicationContext);
evaluator.init(Collections.<String, String>emptyMap());
evaluator.setExpressionFactory(
JspFactory.getDefaultFactory().getJspApplicationContext(servletContext).getExpressionFactory());
evaluator.setResolver(new CompositeELResolverImpl());
return evaluator;
}
}
private static class CompositeELResolverImpl extends CompositeELResolver {
public CompositeELResolverImpl() {
add(new ScopeELResolver());
add(new TilesContextELResolver(new TilesContextBeanELResolver()));
add(new TilesContextBeanELResolver());
add(new ArrayELResolver(false));
add(new ListELResolver(false));
add(new MapELResolver(false));
add(new ResourceBundleELResolver());
add(new BeanELResolver(false));
}
}
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright 2002-2013 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles3;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.tiles.TilesContainer;
import org.apache.tiles.access.TilesAccess;
import org.apache.tiles.renderer.DefinitionRenderer;
import org.apache.tiles.request.ApplicationContext;
import org.apache.tiles.request.Request;
import org.apache.tiles.request.render.Renderer;
import org.apache.tiles.request.servlet.ServletRequest;
import org.apache.tiles.request.servlet.ServletUtil;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.support.JstlUtils;
import org.springframework.web.servlet.support.RequestContext;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.servlet.view.AbstractUrlBasedView;
/**
* {@link org.springframework.web.servlet.View} implementation that renders
* through the Tiles Request API. The "url" property is interpreted as name of a
* Tiles definition.
*
* @author Nicolas Le Bas
* @author mick semb wever
* @author Rossen Stoyanchev
* @since 3.2
*/
public class TilesView extends AbstractUrlBasedView {
private Renderer renderer;
private boolean exposeJstlAttributes = true;
private ApplicationContext applicationContext;
/**
* Set the {@link Renderer} to use.
* If not set, by default {@link DefinitionRenderer} is used.
*/
public void setRenderer(Renderer renderer) {
this.renderer = renderer;
}
/**
* Whether to expose JSTL attributes. By default set to {@code true}.
* @see JstlUtils#exposeLocalizationContext(RequestContext)
*/
protected void setExposeJstlAttributes(boolean exposeJstlAttributes) {
this.exposeJstlAttributes = exposeJstlAttributes;
}
@Override
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
this.applicationContext = ServletUtil.getApplicationContext(getServletContext());
if (this.renderer == null) {
TilesContainer container = TilesAccess.getContainer(this.applicationContext);
this.renderer = new DefinitionRenderer(container);
}
}
@Override
public boolean checkResource(final Locale locale) throws Exception {
HttpServletRequest servletRequest = null;
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes instanceof ServletRequestAttributes) {
servletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
}
Request request = new ServletRequest(this.applicationContext, servletRequest, null) {
@Override
public Locale getRequestLocale() {
return locale;
}
};
return this.renderer.isRenderable(getUrl(), request);
}
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
exposeModelAsRequestAttributes(model, request);
if (this.exposeJstlAttributes) {
JstlUtils.exposeLocalizationContext(new RequestContext(request, getServletContext()));
}
Request tilesRequest = createTilesRequest(request, response);
this.renderer.render(getUrl(), tilesRequest);
}
/**
* Create a Tiles {@link Request}.
* <p>This implementation creates a {@link ServletRequest}.
* @param request the current request
* @param response the current response
* @return the Tiles request
*/
protected Request createTilesRequest(final HttpServletRequest request, HttpServletResponse response) {
return new ServletRequest(this.applicationContext, request, response) {
@Override
public Locale getRequestLocale() {
return RequestContextUtils.getLocale(request);
}
};
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2002-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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.view.tiles3;
import org.apache.tiles.request.render.Renderer;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
/**
* Convenience subclass of {@link UrlBasedViewResolver} that supports
* {@link TilesView} (i.e. Tiles definitions) and custom subclasses of it.
*
* @author Nicolas Le Bas
* @author Rossen Stoyanchev
* @since 3.2
*/
public class TilesViewResolver extends UrlBasedViewResolver {
private Renderer renderer;
@Override
protected Class<?> getViewClass() {
return TilesView.class;
}
/**
* Set the {@link Renderer} to use. If not set, by default
* {@link org.apache.tiles.renderer.DefinitionRenderer} is used.
* @see TilesView#setRenderer(Renderer)
*/
public void setRenderer(Renderer renderer) {
this.renderer = renderer;
}
@Override
protected TilesView buildView(String viewName) throws Exception {
TilesView view = (TilesView) super.buildView(viewName);
view.setRenderer(this.renderer);
return view;
}
}

View File

@@ -2,10 +2,10 @@
/**
*
* Support classes for the integration of
* <a href="http://tiles.apache.org">Tiles2</a>
* <a href="http://tiles.apache.org">Tiles3</a>
* (the standalone version of Tiles) as Spring web view technology.
* Contains a View implementation for Tiles definitions.
*
*/
package org.springframework.web.servlet.view.tiles2;
package org.springframework.web.servlet.view.tiles3;