View Javadoc

1   /*
2    * $Id: CompleteAutoloadTilesContainerFactory.java 836356 2009-11-15 13:27:43Z apetrelli $
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.IOException;
25  import java.net.URL;
26  import java.util.HashSet;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Set;
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.TilesApplicationContext;
44  import org.apache.tiles.TilesContainer;
45  import org.apache.tiles.compat.definition.digester.CompatibilityDigesterDefinitionsReader;
46  import org.apache.tiles.context.ChainedTilesRequestContextFactory;
47  import org.apache.tiles.context.TilesRequestContext;
48  import org.apache.tiles.context.TilesRequestContextFactory;
49  import org.apache.tiles.context.TilesRequestContextHolder;
50  import org.apache.tiles.definition.DefinitionsFactoryException;
51  import org.apache.tiles.definition.DefinitionsReader;
52  import org.apache.tiles.definition.pattern.DefinitionPatternMatcherFactory;
53  import org.apache.tiles.definition.pattern.PatternDefinitionResolver;
54  import org.apache.tiles.definition.pattern.PrefixedPatternDefinitionResolver;
55  import org.apache.tiles.definition.pattern.regexp.RegexpDefinitionPatternMatcherFactory;
56  import org.apache.tiles.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory;
57  import org.apache.tiles.el.ELAttributeEvaluator;
58  import org.apache.tiles.el.JspExpressionFactoryFactory;
59  import org.apache.tiles.el.TilesContextBeanELResolver;
60  import org.apache.tiles.el.TilesContextELResolver;
61  import org.apache.tiles.evaluator.AttributeEvaluatorFactory;
62  import org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory;
63  import org.apache.tiles.factory.BasicTilesContainerFactory;
64  import org.apache.tiles.factory.TilesContainerFactoryException;
65  import org.apache.tiles.freemarker.context.FreeMarkerTilesRequestContextFactory;
66  import org.apache.tiles.freemarker.renderer.FreeMarkerAttributeRenderer;
67  import org.apache.tiles.impl.BasicTilesContainer;
68  import org.apache.tiles.impl.mgmt.CachingTilesContainer;
69  import org.apache.tiles.locale.LocaleResolver;
70  import org.apache.tiles.mvel.MVELAttributeEvaluator;
71  import org.apache.tiles.mvel.TilesContextBeanVariableResolverFactory;
72  import org.apache.tiles.mvel.TilesContextVariableResolverFactory;
73  import org.apache.tiles.ognl.ApplicationScopeNestedObjectExtractor;
74  import org.apache.tiles.ognl.DelegatePropertyAccessor;
75  import org.apache.tiles.ognl.NestedObjectDelegatePropertyAccessor;
76  import org.apache.tiles.ognl.OGNLAttributeEvaluator;
77  import org.apache.tiles.ognl.PropertyAccessorDelegateFactory;
78  import org.apache.tiles.ognl.RequestScopeNestedObjectExtractor;
79  import org.apache.tiles.ognl.SessionScopeNestedObjectExtractor;
80  import org.apache.tiles.ognl.TilesApplicationContextNestedObjectExtractor;
81  import org.apache.tiles.ognl.TilesContextPropertyAccessorDelegateFactory;
82  import org.apache.tiles.renderer.AttributeRenderer;
83  import org.apache.tiles.renderer.TypeDetectingAttributeRenderer;
84  import org.apache.tiles.renderer.impl.BasicRendererFactory;
85  import org.apache.tiles.renderer.impl.ChainedDelegateAttributeRenderer;
86  import org.apache.tiles.util.URLUtil;
87  import org.apache.tiles.velocity.context.VelocityTilesRequestContextFactory;
88  import org.apache.tiles.velocity.renderer.VelocityAttributeRenderer;
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 and FreeMarker 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: 836356 $ $Date: 2009-11-15 14:27:43 +0100 (dom, 15 nov 2009) $
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     /*** {@inheritDoc} */
120     @Override
121     protected BasicTilesContainer instantiateContainer(
122             TilesApplicationContext applicationContext) {
123         return new CachingTilesContainer();
124     }
125 
126     /*** {@inheritDoc} */
127     @Override
128     protected List<TilesRequestContextFactory> getTilesRequestContextFactoriesToBeChained(
129             ChainedTilesRequestContextFactory parent) {
130         List<TilesRequestContextFactory> factories = super.getTilesRequestContextFactoriesToBeChained(parent);
131         registerRequestContextFactory(
132                 FreeMarkerTilesRequestContextFactory.class.getName(),
133                 factories, parent);
134         registerRequestContextFactory(
135                 VelocityTilesRequestContextFactory.class.getName(),
136                 factories, parent);
137         return factories;
138     }
139 
140     /*** {@inheritDoc} */
141     @Override
142     protected void registerAttributeRenderers(
143             BasicRendererFactory rendererFactory,
144             TilesApplicationContext applicationContext,
145             TilesRequestContextFactory contextFactory,
146             TilesContainer container,
147             AttributeEvaluatorFactory attributeEvaluatorFactory) {
148         super.registerAttributeRenderers(rendererFactory, applicationContext, contextFactory,
149                 container, attributeEvaluatorFactory);
150 
151         FreeMarkerAttributeRenderer freemarkerRenderer = new FreeMarkerAttributeRenderer();
152         freemarkerRenderer.setApplicationContext(applicationContext);
153         freemarkerRenderer.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
154         freemarkerRenderer.setRequestContextFactory(contextFactory);
155         freemarkerRenderer.setParameter("TemplatePath", "/");
156         freemarkerRenderer.setParameter("NoCache", "true");
157         freemarkerRenderer.setParameter("ContentType", "text/html");
158         freemarkerRenderer.setParameter("template_update_delay", "0");
159         freemarkerRenderer.setParameter("default_encoding", "ISO-8859-1");
160         freemarkerRenderer.setParameter("number_format", "0.##########");
161         freemarkerRenderer.commit();
162         rendererFactory.registerRenderer(FREEMARKER_RENDERER_NAME, freemarkerRenderer);
163 
164         VelocityAttributeRenderer velocityRenderer = new VelocityAttributeRenderer();
165         velocityRenderer.setApplicationContext(applicationContext);
166         velocityRenderer.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
167         velocityRenderer.setRequestContextFactory(contextFactory);
168         velocityRenderer.commit();
169         rendererFactory.registerRenderer(VELOCITY_RENDERER_NAME, velocityRenderer);
170     }
171 
172 
173 
174     /*** {@inheritDoc} */
175     @Override
176     protected AttributeRenderer createDefaultAttributeRenderer(
177             BasicRendererFactory rendererFactory,
178             TilesApplicationContext applicationContext,
179             TilesRequestContextFactory contextFactory,
180             TilesContainer container,
181             AttributeEvaluatorFactory attributeEvaluatorFactory) {
182         ChainedDelegateAttributeRenderer retValue = new ChainedDelegateAttributeRenderer();
183         retValue.addAttributeRenderer((TypeDetectingAttributeRenderer) rendererFactory
184                 .getRenderer(DEFINITION_RENDERER_NAME));
185         retValue.addAttributeRenderer((TypeDetectingAttributeRenderer) rendererFactory
186                 .getRenderer(VELOCITY_RENDERER_NAME));
187         retValue.addAttributeRenderer((TypeDetectingAttributeRenderer) rendererFactory
188                 .getRenderer(FREEMARKER_RENDERER_NAME));
189         retValue.addAttributeRenderer((TypeDetectingAttributeRenderer) rendererFactory
190                 .getRenderer(TEMPLATE_RENDERER_NAME));
191         retValue.addAttributeRenderer((TypeDetectingAttributeRenderer) rendererFactory
192                 .getRenderer(STRING_RENDERER_NAME));
193         retValue.setApplicationContext(applicationContext);
194         retValue.setRequestContextFactory(contextFactory);
195         retValue.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
196         return retValue;
197     }
198 
199     /*** {@inheritDoc} */
200     @Override
201     protected AttributeEvaluatorFactory createAttributeEvaluatorFactory(
202             TilesApplicationContext applicationContext,
203             TilesRequestContextFactory contextFactory, LocaleResolver resolver) {
204         BasicAttributeEvaluatorFactory attributeEvaluatorFactory = new BasicAttributeEvaluatorFactory(
205                 createELEvaluator(applicationContext));
206         attributeEvaluatorFactory.registerAttributeEvaluator("MVEL",
207                 createMVELEvaluator());
208         attributeEvaluatorFactory.registerAttributeEvaluator("OGNL",
209                 createOGNLEvaluator());
210 
211         return attributeEvaluatorFactory;
212     }
213 
214     /*** {@inheritDoc} */
215     @Override
216     protected <T> PatternDefinitionResolver<T> createPatternDefinitionResolver(
217             Class<T> customizationKeyClass) {
218         DefinitionPatternMatcherFactory wildcardFactory = new WildcardDefinitionPatternMatcherFactory();
219         DefinitionPatternMatcherFactory regexpFactory = new RegexpDefinitionPatternMatcherFactory();
220         PrefixedPatternDefinitionResolver<T> resolver = new PrefixedPatternDefinitionResolver<T>();
221         resolver.registerDefinitionPatternMatcherFactory("WILDCARD", wildcardFactory);
222         resolver.registerDefinitionPatternMatcherFactory("REGEXP", regexpFactory);
223         return resolver;
224     }
225 
226     /*** {@inheritDoc} */
227     @Override
228     protected List<URL> getSourceURLs(TilesApplicationContext applicationContext,
229             TilesRequestContextFactory contextFactory) {
230         try {
231             Set<URL> finalSet = new HashSet<URL>();
232             Set<URL> webINFSet = applicationContext.getResources("/WEB-INF/**/tiles*.xml");
233             Set<URL> metaINFSet = applicationContext.getResources("classpath*:META-INF/**/tiles*.xml");
234 
235             if (webINFSet != null) {
236                 finalSet.addAll(webINFSet);
237             }
238             if (metaINFSet != null) {
239                 finalSet.addAll(metaINFSet);
240             }
241 
242             return URLUtil.getBaseTilesDefinitionURLs(finalSet);
243         } catch (IOException e) {
244             throw new DefinitionsFactoryException(
245                     "Cannot load definition URLs", e);
246         }
247     }
248 
249     /*** {@inheritDoc} */
250     @Override
251     protected DefinitionsReader createDefinitionsReader(TilesApplicationContext applicationContext,
252             TilesRequestContextFactory contextFactory) {
253         return new CompatibilityDigesterDefinitionsReader();
254     }
255 
256     /***
257      * Creates the EL evaluator.
258      *
259      * @param applicationContext The Tiles application context.
260      * @return The EL evaluator.
261      */
262     private ELAttributeEvaluator createELEvaluator(
263             TilesApplicationContext applicationContext) {
264         ELAttributeEvaluator evaluator = new ELAttributeEvaluator();
265         evaluator.setApplicationContext(applicationContext);
266         JspExpressionFactoryFactory efFactory = new JspExpressionFactoryFactory();
267         efFactory.setApplicationContext(applicationContext);
268         evaluator.setExpressionFactory(efFactory.getExpressionFactory());
269         ELResolver elResolver = new CompositeELResolver() {
270             {
271                 add(new TilesContextELResolver());
272                 add(new TilesContextBeanELResolver());
273                 add(new ArrayELResolver(false));
274                 add(new ListELResolver(false));
275                 add(new MapELResolver(false));
276                 add(new ResourceBundleELResolver());
277                 add(new BeanELResolver(false));
278             }
279         };
280         evaluator.setResolver(elResolver);
281         return evaluator;
282     }
283 
284     /***
285      * Creates the MVEL evaluator.
286      *
287      * @return The MVEL evaluator.
288      */
289     private MVELAttributeEvaluator createMVELEvaluator() {
290         TilesRequestContextHolder requestHolder = new TilesRequestContextHolder();
291         VariableResolverFactory variableResolverFactory = new TilesContextVariableResolverFactory(
292                 requestHolder);
293         variableResolverFactory
294                 .setNextFactory(new TilesContextBeanVariableResolverFactory(
295                         requestHolder));
296         MVELAttributeEvaluator mvelEvaluator = new MVELAttributeEvaluator(requestHolder,
297                 variableResolverFactory);
298         return mvelEvaluator;
299     }
300 
301     /***
302      * Creates the OGNL evaluator.
303      *
304      * @return The OGNL evaluator.
305      */
306     private OGNLAttributeEvaluator createOGNLEvaluator() {
307         try {
308             PropertyAccessor objectPropertyAccessor = OgnlRuntime.getPropertyAccessor(Object.class);
309             PropertyAccessor mapPropertyAccessor = OgnlRuntime.getPropertyAccessor(Map.class);
310             PropertyAccessor applicationContextPropertyAccessor =
311                 new NestedObjectDelegatePropertyAccessor<TilesRequestContext>(
312                     new TilesApplicationContextNestedObjectExtractor(),
313                     objectPropertyAccessor);
314             PropertyAccessor requestScopePropertyAccessor =
315                 new NestedObjectDelegatePropertyAccessor<TilesRequestContext>(
316                     new RequestScopeNestedObjectExtractor(), mapPropertyAccessor);
317             PropertyAccessor sessionScopePropertyAccessor =
318                 new NestedObjectDelegatePropertyAccessor<TilesRequestContext>(
319                     new SessionScopeNestedObjectExtractor(), mapPropertyAccessor);
320             PropertyAccessor applicationScopePropertyAccessor =
321                 new NestedObjectDelegatePropertyAccessor<TilesRequestContext>(
322                     new ApplicationScopeNestedObjectExtractor(), mapPropertyAccessor);
323             PropertyAccessorDelegateFactory<TilesRequestContext> factory =
324                 new TilesContextPropertyAccessorDelegateFactory(
325                     objectPropertyAccessor, applicationContextPropertyAccessor,
326                     requestScopePropertyAccessor, sessionScopePropertyAccessor,
327                     applicationScopePropertyAccessor);
328             PropertyAccessor tilesRequestAccessor = new DelegatePropertyAccessor<TilesRequestContext>(factory);
329             OgnlRuntime.setPropertyAccessor(TilesRequestContext.class, tilesRequestAccessor);
330             return new OGNLAttributeEvaluator();
331         } catch (OgnlException e) {
332             throw new TilesContainerFactoryException(
333                     "Cannot initialize OGNL evaluator", e);
334         }
335     }
336 }