1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 }