This project has retired. For details please refer to its Attic page.
BasicTilesContainerFactory xref
View Javadoc

1   /*
2    * $Id: BasicTilesContainerFactory.java 822631 2009-10-07 09:21:12Z 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  package org.apache.tiles.factory;
22  
23  import java.io.IOException;
24  import java.net.URL;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.Locale;
28  
29  import org.apache.tiles.TilesApplicationContext;
30  import org.apache.tiles.TilesContainer;
31  import org.apache.tiles.awareness.TilesRequestContextFactoryAware;
32  import org.apache.tiles.context.ChainedTilesRequestContextFactory;
33  import org.apache.tiles.context.TilesRequestContextFactory;
34  import org.apache.tiles.definition.DefinitionsFactory;
35  import org.apache.tiles.definition.DefinitionsReader;
36  import org.apache.tiles.definition.Refreshable;
37  import org.apache.tiles.definition.UnresolvingLocaleDefinitionsFactory;
38  import org.apache.tiles.definition.dao.BaseLocaleUrlDefinitionDAO;
39  import org.apache.tiles.definition.dao.DefinitionDAO;
40  import org.apache.tiles.definition.dao.ResolvingLocaleUrlDefinitionDAO;
41  import org.apache.tiles.definition.digester.DigesterDefinitionsReader;
42  import org.apache.tiles.definition.pattern.BasicPatternDefinitionResolver;
43  import org.apache.tiles.definition.pattern.PatternDefinitionResolver;
44  import org.apache.tiles.definition.pattern.PatternDefinitionResolverAware;
45  import org.apache.tiles.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory;
46  import org.apache.tiles.evaluator.AttributeEvaluatorFactory;
47  import org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory;
48  import org.apache.tiles.evaluator.impl.DirectAttributeEvaluator;
49  import org.apache.tiles.impl.BasicTilesContainer;
50  import org.apache.tiles.locale.LocaleResolver;
51  import org.apache.tiles.locale.impl.DefaultLocaleResolver;
52  import org.apache.tiles.preparer.BasicPreparerFactory;
53  import org.apache.tiles.preparer.PreparerFactory;
54  import org.apache.tiles.reflect.ClassUtil;
55  import org.apache.tiles.renderer.AttributeRenderer;
56  import org.apache.tiles.renderer.RendererFactory;
57  import org.apache.tiles.renderer.TypeDetectingAttributeRenderer;
58  import org.apache.tiles.renderer.impl.BasicRendererFactory;
59  import org.apache.tiles.renderer.impl.DefinitionAttributeRenderer;
60  import org.apache.tiles.renderer.impl.StringAttributeRenderer;
61  import org.apache.tiles.renderer.impl.TemplateAttributeRenderer;
62  import org.apache.tiles.renderer.impl.ChainedDelegateAttributeRenderer;
63  import org.slf4j.Logger;
64  import org.slf4j.LoggerFactory;
65  
66  /***
67   * Factory that builds a standard Tiles container using only Java code.
68   *
69   * @version $Rev: 822631 $ $Date: 2009-10-07 11:21:12 +0200 (mer, 07 ott 2009) $
70   * @since 2.1.0
71   */
72  public class BasicTilesContainerFactory extends AbstractTilesContainerFactory {
73  
74      /***
75       * The string renderer name.
76       */
77      protected static final String STRING_RENDERER_NAME = "string";
78  
79      /***
80       * The template renderer name.
81       */
82      protected static final String TEMPLATE_RENDERER_NAME = "template";
83  
84      /***
85       * The definition renderer name.
86       */
87      protected static final String DEFINITION_RENDERER_NAME = "definition";
88      /***
89       * The logging object.
90       */
91      private final Logger log = LoggerFactory
92              .getLogger(BasicTilesContainerFactory.class);
93  
94      /*** {@inheritDoc} */
95      @Override
96      public TilesContainer createContainer(TilesApplicationContext applicationContext) {
97          BasicTilesContainer container = instantiateContainer(applicationContext);
98          TilesRequestContextFactory requestContextFactory =
99              createRequestContextFactory(applicationContext);
100         container.setRequestContextFactory(requestContextFactory);
101         container.setApplicationContext(applicationContext);
102         LocaleResolver resolver = createLocaleResolver(applicationContext,
103                 requestContextFactory);
104         container.setDefinitionsFactory(createDefinitionsFactory(applicationContext,
105                 requestContextFactory, resolver));
106         AttributeEvaluatorFactory attributeEvaluatorFactory = createAttributeEvaluatorFactory(
107                 applicationContext, requestContextFactory, resolver);
108         container.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
109         container.setPreparerFactory(createPreparerFactory(applicationContext,
110                 requestContextFactory));
111         container.setRendererFactory(createRendererFactory(applicationContext,
112                 requestContextFactory, container, attributeEvaluatorFactory));
113         return container;
114     }
115 
116     /***
117      * Instantiate the container, without initialization.
118      *
119      * @param context The Tiles application context object.
120      * @return The instantiated container.
121      * @since 2.1.1
122      */
123     protected BasicTilesContainer instantiateContainer(
124             TilesApplicationContext context) {
125         return new BasicTilesContainer();
126     }
127 
128     /***
129      * Create a Tiles request context factory. By default it creates a
130      * {@link ChainedTilesRequestContextFactory}.
131      *
132      * @param context The Tiles application context.
133      * @return The request context factory.
134      * @since 2.1.1
135      */
136     protected TilesRequestContextFactory createRequestContextFactory(
137             TilesApplicationContext context) {
138         ChainedTilesRequestContextFactory contextFactory = new ChainedTilesRequestContextFactory();
139         registerChainedRequestContextFactories(contextFactory);
140 
141         return contextFactory;
142     }
143 
144     /***
145      * Register elements of a chained request context factory.
146      *
147      * @param contextFactory The request context factory to use.
148      * @since 2.1.1
149      */
150     protected void registerChainedRequestContextFactories(
151             ChainedTilesRequestContextFactory contextFactory) {
152         List<TilesRequestContextFactory> factories = getTilesRequestContextFactoriesToBeChained(contextFactory);
153         contextFactory.setFactories(factories);
154     }
155 
156     /***
157      * Returns the list of {@link TilesRequestContextFactory} instances to be
158      * chained together.
159      *
160      * @param parent The parent factory.
161      * @return The list of factories.
162      * @since 2.2.0
163      */
164     protected List<TilesRequestContextFactory> getTilesRequestContextFactoriesToBeChained(
165             ChainedTilesRequestContextFactory parent) {
166         List<TilesRequestContextFactory> factories = new ArrayList<TilesRequestContextFactory>();
167         registerRequestContextFactory(
168                 "org.apache.tiles.servlet.context.ServletTilesRequestContextFactory",
169                 factories, parent);
170         registerRequestContextFactory(
171                 "org.apache.tiles.portlet.context.PortletTilesRequestContextFactory",
172                 factories, parent);
173         registerRequestContextFactory(
174                 "org.apache.tiles.jsp.context.JspTilesRequestContextFactory",
175                 factories, parent);
176         return factories;
177     }
178 
179     /***
180      * Registers a {@link TilesRequestContextFactory} specifying its
181      * classname.
182      *
183      * @param className The name of the class to instantiate.
184      * @param factories The list of factories to add to.
185      * @param parent The parent {@link TilesRequestContextFactory}. If null
186      * it won't be considered.
187      * @since 2.1.1
188      */
189     protected void registerRequestContextFactory(String className,
190             List<TilesRequestContextFactory> factories,
191             TilesRequestContextFactory parent) {
192         TilesRequestContextFactory retValue = null;
193         try {
194             Class<? extends TilesRequestContextFactory> clazz = ClassUtil
195                     .getClass(className, TilesRequestContextFactory.class);
196             retValue = clazz.newInstance();
197             if (parent != null
198                     && retValue instanceof TilesRequestContextFactoryAware) {
199                 ((TilesRequestContextFactoryAware) retValue)
200                         .setRequestContextFactory(parent);
201             }
202         } catch (ClassNotFoundException e) {
203             if (log.isDebugEnabled()) {
204                 log.debug("Cannot find class '" + className + "', ignoring problem", e);
205             }
206         } catch (NotAvailableFeatureException e) {
207             if (log.isDebugEnabled()) {
208                 log.debug("Not available feature exception during instantiation of class '"
209                         + className + "', ignoring problem", e);
210             }
211         } catch (InstantiationException e) {
212             throw new TilesContainerFactoryException(
213                     "Cannot instantiate '" + className + "'", e);
214         } catch (IllegalAccessException e) {
215             throw new TilesContainerFactoryException(
216                     "Cannot access default constructor '" + className + "'",
217                     e);
218         }
219         if (retValue != null) {
220             factories.add(retValue);
221         }
222     }
223 
224     /***
225      * Creates the definitions factory. By default it creates a
226      * {@link UnresolvingLocaleDefinitionsFactory} with default dependencies.
227      *
228      * @param applicationContext The Tiles application context.
229      * @param contextFactory The Tiles context factory.
230      * @param resolver The locale resolver.
231      *
232      * @return The definitions factory.
233      * @since 2.1.1
234      */
235     protected DefinitionsFactory createDefinitionsFactory(TilesApplicationContext applicationContext,
236             TilesRequestContextFactory contextFactory,
237             LocaleResolver resolver) {
238         UnresolvingLocaleDefinitionsFactory factory = instantiateDefinitionsFactory(
239                 applicationContext, contextFactory, resolver);
240         factory.setApplicationContext(applicationContext);
241         factory.setLocaleResolver(resolver);
242         factory.setDefinitionDAO(createLocaleDefinitionDao(applicationContext,
243                 contextFactory, resolver));
244         if (factory instanceof Refreshable) {
245             ((Refreshable) factory).refresh();
246         }
247         return factory;
248     }
249 
250     /***
251      * Instantiate a new definitions factory based on Locale.
252      * @param applicationContext The Tiles application context.
253      * @param contextFactory The Tiles context factory.
254      * @param resolver The locale resolver.
255      *
256      * @return The definitions factory.
257      * @since 2.2.1
258      */
259     protected UnresolvingLocaleDefinitionsFactory instantiateDefinitionsFactory(
260             TilesApplicationContext applicationContext,
261             TilesRequestContextFactory contextFactory, LocaleResolver resolver) {
262         return new UnresolvingLocaleDefinitionsFactory();
263     }
264 
265 
266     /***
267      * Instantiate (and does not initialize) a Locale-based definition DAO.
268      * @param applicationContext The Tiles application context.
269      * @param contextFactory The Tiles context factory.
270      * @param resolver The locale resolver.
271      *
272      * @return The definition DAO.
273      * @since 2.1.1
274      */
275     protected BaseLocaleUrlDefinitionDAO instantiateLocaleDefinitionDao(TilesApplicationContext applicationContext,
276             TilesRequestContextFactory contextFactory,
277             LocaleResolver resolver) {
278         ResolvingLocaleUrlDefinitionDAO dao = new ResolvingLocaleUrlDefinitionDAO();
279         return dao;
280     }
281 
282     /***
283      * Creates a Locale-based definition DAO.
284      * @param applicationContext The Tiles application context.
285      * @param contextFactory The Tiles context factory.
286      * @param resolver The locale resolver.
287      *
288      * @return The definition DAO.
289      * @since 2.1.1
290      */
291     @SuppressWarnings("unchecked")
292     protected DefinitionDAO<Locale> createLocaleDefinitionDao(TilesApplicationContext applicationContext,
293             TilesRequestContextFactory contextFactory,
294             LocaleResolver resolver) {
295         BaseLocaleUrlDefinitionDAO definitionDao = instantiateLocaleDefinitionDao(
296                 applicationContext, contextFactory, resolver);
297         definitionDao.setReader(createDefinitionsReader(applicationContext, contextFactory));
298         definitionDao.setSourceURLs(getSourceURLs(applicationContext, contextFactory));
299         definitionDao.setApplicationContext(applicationContext);
300         if (definitionDao instanceof PatternDefinitionResolverAware) {
301             ((PatternDefinitionResolverAware<Locale>) definitionDao)
302                     .setPatternDefinitionResolver(createPatternDefinitionResolver(Locale.class));
303         }
304         return definitionDao;
305     }
306 
307     /***
308      * Creates the locale resolver. By default it creates a
309      * {@link DefaultLocaleResolver}.
310      * @param applicationContext The Tiles application context.
311      * @param contextFactory The Tiles context factory.
312      *
313      * @return The locale resolver.
314      * @since 2.1.1
315      */
316     protected LocaleResolver createLocaleResolver(TilesApplicationContext applicationContext,
317             TilesRequestContextFactory contextFactory) {
318         return new DefaultLocaleResolver();
319     }
320 
321     /***
322      * Creates the definitions reader. By default it creates a
323      * {@link DigesterDefinitionsReader}.
324      * @param applicationContext The Tiles application context.
325      * @param contextFactory The Tiles context factory.
326      *
327      * @return The definitions reader.
328      * @since 2.1.1
329      */
330     protected DefinitionsReader createDefinitionsReader(
331             TilesApplicationContext applicationContext,
332             TilesRequestContextFactory contextFactory) {
333         return new DigesterDefinitionsReader();
334     }
335 
336     /***
337      * Returns a list containing the URLs to be parsed. By default, it returns a
338      * list containing the URL point to "/WEB-INF/tiles.xml".
339      * @param applicationContext The Tiles application context.
340      * @param contextFactory The Tiles context factory.
341      *
342      * @return The source URLs.
343      * @since 2.1.1
344      */
345     protected List<URL> getSourceURLs(TilesApplicationContext applicationContext,
346             TilesRequestContextFactory contextFactory) {
347         List<URL> retValue = new ArrayList<URL>(1);
348         try {
349             retValue.add(applicationContext.getResource("/WEB-INF/tiles.xml"));
350         } catch (IOException e) {
351             throw new TilesContainerFactoryException(
352                     "Cannot get URL: /WEB-INF/tiles.xml", e);
353         }
354         return retValue;
355     }
356 
357     /***
358      * Creates the attribute evaluator factory to use. By default it returns a
359      * {@link BasicAttributeEvaluatorFactory} containing the
360      * {@link DirectAttributeEvaluator} as the default evaluator.
361      *
362      * @param applicationContext The Tiles application context.
363      * @param contextFactory The Tiles context factory.
364      * @param resolver The locale resolver.
365      *
366      * @return The evaluator factory.
367      * @since 2.2.0
368      */
369     protected AttributeEvaluatorFactory createAttributeEvaluatorFactory(
370             TilesApplicationContext applicationContext,
371             TilesRequestContextFactory contextFactory, LocaleResolver resolver) {
372         return new BasicAttributeEvaluatorFactory(new DirectAttributeEvaluator());
373     }
374 
375     /***
376      * Creates the preparer factory to use. By default it returns a
377      * {@link BasicPreparerFactory}.
378      * @param applicationContext The Tiles application context.
379      * @param contextFactory The Tiles context factory.
380      *
381      * @return The preparer factory.
382      * @since 2.1.1
383      */
384     protected PreparerFactory createPreparerFactory(TilesApplicationContext applicationContext,
385             TilesRequestContextFactory contextFactory) {
386         return new BasicPreparerFactory();
387     }
388 
389     /***
390      * Creates a renderer factory. By default it returns a
391      * {@link BasicRendererFactory}, composed of an
392      * {@link UntypedAttributeRenderer} as default, and
393      * {@link StringAttributeRenderer}, {@link TemplateAttributeRenderer} and
394      * {@link DefinitionAttributeRenderer}.
395      * @param applicationContext The Tiles application context.
396      * @param contextFactory The Tiles context factory.
397      * @param container The container.
398      * @param attributeEvaluatorFactory The attribute evaluator factory.
399      *
400      * @return The renderer factory.
401      * @since 2.2.0
402      */
403     protected RendererFactory createRendererFactory(TilesApplicationContext applicationContext,
404             TilesRequestContextFactory contextFactory,
405             TilesContainer container, AttributeEvaluatorFactory attributeEvaluatorFactory) {
406         BasicRendererFactory retValue = new BasicRendererFactory();
407         retValue.setApplicationContext(applicationContext);
408         retValue.setRequestContextFactory(contextFactory);
409         retValue.setContainer(container);
410         retValue.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
411         registerAttributeRenderers(retValue, applicationContext, contextFactory,
412                 container, attributeEvaluatorFactory);
413         retValue.setDefaultRenderer(createDefaultAttributeRenderer(retValue,
414                 applicationContext, contextFactory, container,
415                 attributeEvaluatorFactory));
416         return retValue;
417     }
418 
419     /***
420      * Creates the default attribute renderer. By default it is an
421      * {@link ChainedDelegateAttributeRenderer}.
422      *
423      * @param rendererFactory The renderer factory to configure.
424      * @param applicationContext The Tiles application context.
425      * @param contextFactory The Tiles context factory.
426      * @param container The container.
427      * @param attributeEvaluatorFactory The attribute evaluator factory.
428      * @return The default attribute renderer.
429      * @since 2.2.1
430      */
431     protected AttributeRenderer createDefaultAttributeRenderer(
432             BasicRendererFactory rendererFactory,
433             TilesApplicationContext applicationContext,
434             TilesRequestContextFactory contextFactory,
435             TilesContainer container,
436             AttributeEvaluatorFactory attributeEvaluatorFactory) {
437         ChainedDelegateAttributeRenderer retValue = new ChainedDelegateAttributeRenderer();
438         retValue.addAttributeRenderer((TypeDetectingAttributeRenderer) rendererFactory
439                 .getRenderer(DEFINITION_RENDERER_NAME));
440         retValue.addAttributeRenderer((TypeDetectingAttributeRenderer) rendererFactory
441                 .getRenderer(TEMPLATE_RENDERER_NAME));
442         retValue.addAttributeRenderer((TypeDetectingAttributeRenderer) rendererFactory
443                 .getRenderer(STRING_RENDERER_NAME));
444         retValue.setApplicationContext(applicationContext);
445         retValue.setRequestContextFactory(contextFactory);
446         retValue.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
447         return retValue;
448     }
449 
450     /***
451      * Creates a new pattern definition resolver. By default, it instantiate a
452      * {@link BasicPatternDefinitionResolver} with
453      * {@link WildcardDefinitionPatternMatcherFactory} to manage wildcard
454      * substitution.
455      *
456      * @param <T> The type of the customization key.
457      * @param customizationKeyClass The customization key class.
458      * @return The pattern definition resolver.
459      * @since 2.2.0
460      */
461     protected <T> PatternDefinitionResolver<T> createPatternDefinitionResolver(
462             Class<T> customizationKeyClass) {
463         WildcardDefinitionPatternMatcherFactory definitionPatternMatcherFactory =
464             new WildcardDefinitionPatternMatcherFactory();
465         return new BasicPatternDefinitionResolver<T>(
466                 definitionPatternMatcherFactory,
467                 definitionPatternMatcherFactory);
468     }
469 
470     /***
471      * Registers attribute renderers in a {@link BasicRendererFactory}. By
472      * default, it registers a {@link StringAttributeRenderer}, a
473      * {@link TemplateAttributeRenderer} and a
474      * {@link DefinitionAttributeRenderer}.
475      *
476      * @param rendererFactory The renderer factory to configure.
477      * @param applicationContext The Tiles application context.
478      * @param contextFactory The Tiles context factory.
479      * @param container The container.
480      * @param attributeEvaluatorFactory The attribute evaluator factory.
481      * @since 2.2.0
482      */
483     protected void registerAttributeRenderers(
484             BasicRendererFactory rendererFactory,
485             TilesApplicationContext applicationContext,
486             TilesRequestContextFactory contextFactory,
487             TilesContainer container,
488             AttributeEvaluatorFactory attributeEvaluatorFactory) {
489         rendererFactory.registerRenderer(STRING_RENDERER_NAME,
490                 createStringAttributeRenderer(rendererFactory,
491                         applicationContext, contextFactory, container,
492                         attributeEvaluatorFactory));
493         rendererFactory.registerRenderer(TEMPLATE_RENDERER_NAME,
494                 createTemplateAttributeRenderer(rendererFactory,
495                         applicationContext, contextFactory, container,
496                         attributeEvaluatorFactory));
497         rendererFactory.registerRenderer(DEFINITION_RENDERER_NAME,
498                 createDefinitionAttributeRenderer(rendererFactory,
499                         applicationContext, contextFactory, container,
500                         attributeEvaluatorFactory));
501     }
502 
503     /***
504      * Creates a {@link StringAttributeRenderer}.
505      *
506      * @param rendererFactory The renderer factory to configure.
507      * @param applicationContext The Tiles application context.
508      * @param contextFactory The Tiles context factory.
509      * @param container The container.
510      * @param attributeEvaluatorFactory The attribute evaluator factory.
511      * @return The renderer.
512      * @since 2.2.1
513      */
514     protected AttributeRenderer createStringAttributeRenderer(
515             BasicRendererFactory rendererFactory,
516             TilesApplicationContext applicationContext,
517             TilesRequestContextFactory contextFactory,
518             TilesContainer container,
519             AttributeEvaluatorFactory attributeEvaluatorFactory) {
520         StringAttributeRenderer stringRenderer = new StringAttributeRenderer();
521         stringRenderer.setApplicationContext(applicationContext);
522         stringRenderer.setRequestContextFactory(contextFactory);
523         stringRenderer.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
524         return stringRenderer;
525     }
526 
527     /***
528      * Creates a {@link TemplateAttributeRenderer}.
529      *
530      * @param rendererFactory The renderer factory to configure.
531      * @param applicationContext The Tiles application context.
532      * @param contextFactory The Tiles context factory.
533      * @param container The container.
534      * @param attributeEvaluatorFactory The attribute evaluator factory.
535      * @return The renderer.
536      * @since 2.2.1
537      */
538     protected AttributeRenderer createTemplateAttributeRenderer(
539             BasicRendererFactory rendererFactory,
540             TilesApplicationContext applicationContext,
541             TilesRequestContextFactory contextFactory,
542             TilesContainer container,
543             AttributeEvaluatorFactory attributeEvaluatorFactory) {
544         TemplateAttributeRenderer templateRenderer = new TemplateAttributeRenderer();
545         templateRenderer.setApplicationContext(applicationContext);
546         templateRenderer.setRequestContextFactory(contextFactory);
547         templateRenderer.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
548         return templateRenderer;
549     }
550 
551     /***
552      * Creates a {@link DefinitionAttributeRenderer}.
553      *
554      * @param rendererFactory The renderer factory to configure.
555      * @param applicationContext The Tiles application context.
556      * @param contextFactory The Tiles context factory.
557      * @param container The container.
558      * @param attributeEvaluatorFactory The attribute evaluator factory.
559      * @return The renderer.
560      * @since 2.2.1
561      */
562     protected AttributeRenderer createDefinitionAttributeRenderer(
563             BasicRendererFactory rendererFactory,
564             TilesApplicationContext applicationContext,
565             TilesRequestContextFactory contextFactory,
566             TilesContainer container,
567             AttributeEvaluatorFactory attributeEvaluatorFactory) {
568         DefinitionAttributeRenderer definitionRenderer = new DefinitionAttributeRenderer();
569         definitionRenderer.setApplicationContext(applicationContext);
570         definitionRenderer.setContainer(container);
571         definitionRenderer.setRequestContextFactory(contextFactory);
572         definitionRenderer.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
573         return definitionRenderer;
574     }
575 }