Project Tiles has retired. For details please refer to its Attic page.
CompleteAutoloadTilesContainerFactory xref
View Javadoc

1   /*
2    * $Id: CompleteAutoloadTilesContainerFactory.java 1332136 2012-04-30 09:34:09Z mck $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.tiles.extras.complete;
23  
24  import java.io.InputStream;
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.List;
28  import java.util.Locale;
29  import java.util.regex.Pattern;
30  
31  import javax.el.ArrayELResolver;
32  import javax.el.BeanELResolver;
33  import javax.el.CompositeELResolver;
34  import javax.el.ELResolver;
35  import javax.el.ListELResolver;
36  import javax.el.MapELResolver;
37  import javax.el.ResourceBundleELResolver;
38  
39  import ognl.OgnlException;
40  import ognl.OgnlRuntime;
41  import ognl.PropertyAccessor;
42  
43  import org.apache.tiles.TilesContainer;
44  import org.apache.tiles.compat.definition.digester.CompatibilityDigesterDefinitionsReader;
45  import org.apache.tiles.context.TilesRequestContextHolder;
46  import org.apache.tiles.definition.DefinitionsReader;
47  import org.apache.tiles.definition.pattern.DefinitionPatternMatcherFactory;
48  import org.apache.tiles.definition.pattern.PatternDefinitionResolver;
49  import org.apache.tiles.definition.pattern.PrefixedPatternDefinitionResolver;
50  import org.apache.tiles.definition.pattern.regexp.RegexpDefinitionPatternMatcherFactory;
51  import org.apache.tiles.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory;
52  import org.apache.tiles.el.ELAttributeEvaluator;
53  import org.apache.tiles.el.JspExpressionFactoryFactory;
54  import org.apache.tiles.el.ScopeELResolver;
55  import org.apache.tiles.el.TilesContextBeanELResolver;
56  import org.apache.tiles.el.TilesContextELResolver;
57  import org.apache.tiles.evaluator.AttributeEvaluatorFactory;
58  import org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory;
59  import org.apache.tiles.factory.BasicTilesContainerFactory;
60  import org.apache.tiles.factory.TilesContainerFactoryException;
61  import org.apache.tiles.freemarker.TilesSharedVariableFactory;
62  import org.apache.tiles.impl.mgmt.CachingTilesContainer;
63  import org.apache.tiles.locale.LocaleResolver;
64  import org.apache.tiles.mvel.MVELAttributeEvaluator;
65  import org.apache.tiles.mvel.ScopeVariableResolverFactory;
66  import org.apache.tiles.mvel.TilesContextBeanVariableResolverFactory;
67  import org.apache.tiles.mvel.TilesContextVariableResolverFactory;
68  import org.apache.tiles.ognl.AnyScopePropertyAccessor;
69  import org.apache.tiles.ognl.DelegatePropertyAccessor;
70  import org.apache.tiles.ognl.NestedObjectDelegatePropertyAccessor;
71  import org.apache.tiles.ognl.OGNLAttributeEvaluator;
72  import org.apache.tiles.ognl.PropertyAccessorDelegateFactory;
73  import org.apache.tiles.ognl.ScopePropertyAccessor;
74  import org.apache.tiles.ognl.TilesApplicationContextNestedObjectExtractor;
75  import org.apache.tiles.ognl.TilesContextPropertyAccessorDelegateFactory;
76  import org.apache.tiles.request.ApplicationContext;
77  import org.apache.tiles.request.ApplicationResource;
78  import org.apache.tiles.request.Request;
79  import org.apache.tiles.request.freemarker.render.FreemarkerRenderer;
80  import org.apache.tiles.request.freemarker.render.FreemarkerRendererBuilder;
81  import org.apache.tiles.request.freemarker.servlet.SharedVariableLoaderFreemarkerServlet;
82  import org.apache.tiles.request.mustache.MustacheRenderer;
83  import org.apache.tiles.request.render.BasicRendererFactory;
84  import org.apache.tiles.request.render.ChainedDelegateRenderer;
85  import org.apache.tiles.request.render.Renderer;
86  import org.apache.tiles.request.servlet.ServletUtil;
87  import org.apache.tiles.request.velocity.render.VelocityRenderer;
88  import org.apache.tiles.request.velocity.render.VelocityRendererBuilder;
89  import org.mvel2.integration.VariableResolverFactory;
90  
91  /**
92   * Tiles container factory that:
93   * <ul>
94   * <li>create supporting objects for Velocity and FreeMarker;</li>
95   * <li>create renderers for Velocity, FreeMarker, and Mustache templates;</li>
96   * <li>allows using EL, MVEL and OGNL as attribute expressions;</li>
97   * <li>allows using Wildcards and Regular Expressions in definition names;</li>
98   * <li>loads Tiles 1.x definition files;</li>
99   * <li>loads all the definition files that have the "tiles*.xml" pattern under
100  * <code>/WEB-INF</code> directory (and subdirectories) and under
101  * <code>META-INF</code> directories (and subdirectories) in every jar.</li>
102  * </ul>
103  *
104  * @version $Rev: 1332136 $ $Date: 2012-04-30 19:34:09 +1000 (Mon, 30 Apr 2012) $
105  * @since 2.2.0
106  */
107 public class CompleteAutoloadTilesContainerFactory extends BasicTilesContainerFactory {
108 
109     /**
110      * The freemarker renderer name.
111      */
112     private static final String FREEMARKER_RENDERER_NAME = "freemarker";
113 
114     /**
115      * The velocity renderer name.
116      */
117     private static final String VELOCITY_RENDERER_NAME = "velocity";
118 
119     /**
120      * The mustache renderer name.
121      */
122     private static final String MUSTACHE_RENDERER_NAME = "mustache";
123 
124     /** {@inheritDoc} */
125     @Override
126     public TilesContainer createDecoratedContainer(TilesContainer originalContainer,
127             ApplicationContext applicationContext) {
128         return new CachingTilesContainer(originalContainer);
129     }
130 
131     /** {@inheritDoc} */
132     @Override
133     protected void registerAttributeRenderers(
134             final BasicRendererFactory rendererFactory,
135             final ApplicationContext applicationContext,
136             final TilesContainer container,
137             final AttributeEvaluatorFactory attributeEvaluatorFactory) {
138         super.registerAttributeRenderers(rendererFactory, applicationContext, container, attributeEvaluatorFactory);
139 
140         FreemarkerRenderer freemarkerRenderer = FreemarkerRendererBuilder
141                 .createInstance()
142                 .setApplicationContext(applicationContext)
143                 .setParameter("TemplatePath", "/")
144                 .setParameter("NoCache", "true")
145                 .setParameter("ContentType", "text/html")
146                 .setParameter("template_update_delay", "0")
147                 .setParameter("default_encoding", "ISO-8859-1")
148                 .setParameter("number_format", "0.##########")
149                 .setParameter(SharedVariableLoaderFreemarkerServlet.CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM,
150                         "tiles," + TilesSharedVariableFactory.class.getName()).build();
151         rendererFactory.registerRenderer(FREEMARKER_RENDERER_NAME, freemarkerRenderer);
152 
153         VelocityRenderer velocityRenderer = VelocityRendererBuilder.createInstance()
154                 .setApplicationContext(applicationContext).build();
155         rendererFactory.registerRenderer(VELOCITY_RENDERER_NAME, velocityRenderer);
156 
157         MustacheRenderer mustacheRenderer = new MustacheRenderer();
158         mustacheRenderer.setAcceptPattern(Pattern.compile(".+\\.mustache"));
159         rendererFactory.registerRenderer(MUSTACHE_RENDERER_NAME, mustacheRenderer);
160     }
161 
162     /** {@inheritDoc} */
163     @Override
164     protected Renderer createDefaultAttributeRenderer(BasicRendererFactory rendererFactory,
165             ApplicationContext applicationContext, TilesContainer container,
166             AttributeEvaluatorFactory attributeEvaluatorFactory) {
167 
168         ChainedDelegateRenderer retValue = new ChainedDelegateRenderer();
169         retValue.addAttributeRenderer(rendererFactory.getRenderer(DEFINITION_RENDERER_NAME));
170         retValue.addAttributeRenderer(rendererFactory.getRenderer(VELOCITY_RENDERER_NAME));
171         retValue.addAttributeRenderer(rendererFactory.getRenderer(FREEMARKER_RENDERER_NAME));
172         retValue.addAttributeRenderer(rendererFactory.getRenderer(MUSTACHE_RENDERER_NAME));
173         retValue.addAttributeRenderer(rendererFactory.getRenderer(TEMPLATE_RENDERER_NAME));
174         retValue.addAttributeRenderer(rendererFactory.getRenderer(STRING_RENDERER_NAME));
175         return retValue;
176     }
177 
178     /** {@inheritDoc} */
179     @Override
180     protected AttributeEvaluatorFactory createAttributeEvaluatorFactory(ApplicationContext applicationContext,
181             LocaleResolver resolver) {
182         BasicAttributeEvaluatorFactory attributeEvaluatorFactory = new BasicAttributeEvaluatorFactory(
183                 createELEvaluator(applicationContext));
184         attributeEvaluatorFactory.registerAttributeEvaluator("MVEL", createMVELEvaluator());
185         attributeEvaluatorFactory.registerAttributeEvaluator("OGNL", createOGNLEvaluator());
186 
187         return attributeEvaluatorFactory;
188     }
189 
190     /** {@inheritDoc} */
191     @Override
192     protected <T> PatternDefinitionResolver<T> createPatternDefinitionResolver(Class<T> customizationKeyClass) {
193         DefinitionPatternMatcherFactory wildcardFactory = new WildcardDefinitionPatternMatcherFactory();
194         DefinitionPatternMatcherFactory regexpFactory = new RegexpDefinitionPatternMatcherFactory();
195         PrefixedPatternDefinitionResolver<T> resolver = new PrefixedPatternDefinitionResolver<T>();
196         resolver.registerDefinitionPatternMatcherFactory("WILDCARD", wildcardFactory);
197         resolver.registerDefinitionPatternMatcherFactory("REGEXP", regexpFactory);
198         return resolver;
199     }
200 
201     /** {@inheritDoc} */
202     @Override
203     protected List<ApplicationResource> getSources(ApplicationContext applicationContext) {
204         Collection<ApplicationResource> webINFSet = applicationContext.getResources("/WEB-INF/**/tiles*.xml");
205         Collection<ApplicationResource> metaINFSet = applicationContext
206                 .getResources("classpath*:META-INF/**/tiles*.xml");
207 
208         List<ApplicationResource> filteredResources = new ArrayList<ApplicationResource>();
209         if (webINFSet != null) {
210             for (ApplicationResource resource : webINFSet) {
211                 if (Locale.ROOT.equals(resource.getLocale())) {
212                     filteredResources.add(resource);
213                 }
214             }
215         }
216         if (metaINFSet != null) {
217             for (ApplicationResource resource : metaINFSet) {
218                 if (Locale.ROOT.equals(resource.getLocale())) {
219                     filteredResources.add(resource);
220                 }
221             }
222         }
223         return filteredResources;
224     }
225 
226     /** {@inheritDoc} */
227     @Override
228     protected DefinitionsReader createDefinitionsReader(ApplicationContext applicationContext) {
229         return new CompatibilityDigesterDefinitionsReader();
230     }
231 
232     /**
233      * Creates the EL evaluator.
234      *
235      * @param applicationContext The Tiles application context.
236      * @return The EL evaluator.
237      */
238     private ELAttributeEvaluator createELEvaluator(ApplicationContext applicationContext) {
239         ELAttributeEvaluator evaluator = new ELAttributeEvaluator();
240         JspExpressionFactoryFactory efFactory = new JspExpressionFactoryFactory();
241         efFactory.setApplicationContext(applicationContext);
242         evaluator.setExpressionFactory(efFactory.getExpressionFactory());
243         ELResolver elResolver = new CompositeELResolver() {
244             {
245                 BeanELResolver beanElResolver = new BeanELResolver(false);
246                 add(new ScopeELResolver());
247                 add(new TilesContextELResolver(beanElResolver));
248                 add(new TilesContextBeanELResolver());
249                 add(new ArrayELResolver(false));
250                 add(new ListELResolver(false));
251                 add(new MapELResolver(false));
252                 add(new ResourceBundleELResolver());
253                 add(beanElResolver);
254             }
255         };
256         evaluator.setResolver(elResolver);
257         return evaluator;
258     }
259 
260     /**
261      * Creates the MVEL evaluator.
262      *
263      * @return The MVEL evaluator.
264      */
265     private MVELAttributeEvaluator createMVELEvaluator() {
266         TilesRequestContextHolder requestHolder = new TilesRequestContextHolder();
267         VariableResolverFactory variableResolverFactory = new ScopeVariableResolverFactory(requestHolder);
268         variableResolverFactory.setNextFactory(new TilesContextVariableResolverFactory(requestHolder));
269         variableResolverFactory.setNextFactory(new TilesContextBeanVariableResolverFactory(requestHolder));
270         MVELAttributeEvaluator mvelEvaluator = new MVELAttributeEvaluator(requestHolder, variableResolverFactory);
271         return mvelEvaluator;
272     }
273 
274     /**
275      * Creates the OGNL evaluator.
276      *
277      * @return The OGNL evaluator.
278      */
279     private OGNLAttributeEvaluator createOGNLEvaluator() {
280         try {
281             PropertyAccessor objectPropertyAccessor = OgnlRuntime.getPropertyAccessor(Object.class);
282             PropertyAccessor applicationContextPropertyAccessor = new NestedObjectDelegatePropertyAccessor<Request>(
283                     new TilesApplicationContextNestedObjectExtractor(), objectPropertyAccessor);
284             PropertyAccessor anyScopePropertyAccessor = new AnyScopePropertyAccessor();
285             PropertyAccessor scopePropertyAccessor = new ScopePropertyAccessor();
286             PropertyAccessorDelegateFactory<Request> factory = new TilesContextPropertyAccessorDelegateFactory(
287                     objectPropertyAccessor, applicationContextPropertyAccessor, anyScopePropertyAccessor,
288                     scopePropertyAccessor);
289             PropertyAccessor tilesRequestAccessor = new DelegatePropertyAccessor<Request>(factory);
290             OgnlRuntime.setPropertyAccessor(Request.class, tilesRequestAccessor);
291             return new OGNLAttributeEvaluator();
292         } catch (OgnlException e) {
293             throw new TilesContainerFactoryException("Cannot initialize OGNL evaluator", e);
294         }
295     }
296 }