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

1   /*
2    * $Id: TilesContainerFactory.java 798944 2009-07-29 15:20:27Z 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.lang.reflect.Method;
24  import java.util.Enumeration;
25  import java.util.HashMap;
26  import java.util.Map;
27  
28  import org.apache.tiles.Initializable;
29  import org.apache.tiles.TilesApplicationContext;
30  import org.apache.tiles.TilesContainer;
31  import org.apache.tiles.awareness.TilesApplicationContextAware;
32  import org.apache.tiles.awareness.TilesContainerAware;
33  import org.apache.tiles.awareness.TilesRequestContextFactoryAware;
34  import org.apache.tiles.context.AbstractTilesApplicationContextFactory;
35  import org.apache.tiles.context.ChainedTilesApplicationContextFactory;
36  import org.apache.tiles.context.ChainedTilesRequestContextFactory;
37  import org.apache.tiles.context.TilesRequestContextFactory;
38  import org.apache.tiles.definition.DefinitionsFactory;
39  import org.apache.tiles.definition.UrlDefinitionsFactory;
40  import org.apache.tiles.evaluator.AttributeEvaluator;
41  import org.apache.tiles.evaluator.AttributeEvaluatorFactory;
42  import org.apache.tiles.evaluator.AttributeEvaluatorFactoryAware;
43  import org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory;
44  import org.apache.tiles.evaluator.impl.DirectAttributeEvaluator;
45  import org.apache.tiles.impl.BasicTilesContainer;
46  import org.apache.tiles.impl.mgmt.CachingTilesContainer;
47  import org.apache.tiles.mgmt.MutableTilesContainer;
48  import org.apache.tiles.preparer.BasicPreparerFactory;
49  import org.apache.tiles.preparer.PreparerFactory;
50  import org.apache.tiles.reflect.ClassUtil;
51  import org.apache.tiles.renderer.RendererFactory;
52  import org.apache.tiles.renderer.impl.BasicRendererFactory;
53  import org.slf4j.Logger;
54  import org.slf4j.LoggerFactory;
55  
56  /***
57   * Factory provided for convenience. This factory creates a default
58   * implementation of the container, initializes, and puts it into service. Uses
59   * initialization parameters to configure all the objects created in this phase.
60   *
61   * @version $Rev: 798944 $ $Date: 2009-07-29 17:20:27 +0200 (mer, 29 lug 2009) $
62   * @since 2.0
63   * @deprecated Please extend {@link AbstractTilesContainerFactory} or use an
64   * already extended class. Parameter-based initialization is no longer
65   * supported.
66   */
67  public class TilesContainerFactory extends AbstractTilesContainerFactory {
68  
69      /***
70       * Initialization parameter that represents the container factory class
71       * name.
72       *
73       * @deprecated Use {@link AbstractTilesContainerFactory#CONTAINER_FACTORY_INIT_PARAM}.
74       */
75      public static final String CONTAINER_FACTORY_INIT_PARAM =
76          "org.apache.tiles.factory.TilesContainerFactory";
77  
78      /***
79       * Initialization parameter that indicates if the container factory is
80       * mutable.
81       */
82      public static final String CONTAINER_FACTORY_MUTABLE_INIT_PARAM =
83          "org.apache.tiles.factory.TilesContainerFactory.MUTABLE";
84  
85      /***
86       * Initialization parameter that represents the context factory class name.
87       *
88       * @deprecated Use {@link AbstractTilesApplicationContextFactory#APPLICATION_CONTEXT_FACTORY_INIT_PARAM} or
89       * {@link #REQUEST_CONTEXT_FACTORY_INIT_PARAM}.
90       */
91      public static final String CONTEXT_FACTORY_INIT_PARAM =
92          "org.apache.tiles.context.TilesContextFactory";
93  
94      /***
95       * Initialization parameter that represents the context factory class name.
96       *
97       * @since 2.1.1
98       */
99      public static final String REQUEST_CONTEXT_FACTORY_INIT_PARAM =
100         "org.apache.tiles.context.TilesRequestContextFactory";
101 
102     /***
103      * Initialization parameter that represents the definitions factory class
104      * name.
105      */
106     public static final String DEFINITIONS_FACTORY_INIT_PARAM =
107         "org.apache.tiles.definition.DefinitionsFactory";
108 
109     /***
110      * Initialization parameter that represents the preparer factory class name.
111      */
112     public static final String PREPARER_FACTORY_INIT_PARAM =
113         "org.apache.tiles.preparer.PreparerFactory";
114 
115     /***
116      * Initialization parameter that represents the renderer factory class name.
117      * @since 2.1.0
118      */
119     public static final String RENDERER_FACTORY_INIT_PARAM =
120         "org.apache.tiles.renderer.RendererFactory";
121 
122     /***
123      * Initialization parameter that represents the attribute evaluator class
124      * name.
125      *
126      * @since 2.1.0
127      */
128     public static final String ATTRIBUTE_EVALUATOR_INIT_PARAM =
129         "org.apache.tiles.evaluator.AttributeEvaluator";
130 
131     /***
132      * The logging object.
133      */
134     private final Logger log = LoggerFactory
135             .getLogger(TilesContainerFactory.class);
136 
137     /***
138      * Default configuration parameters.
139      */
140     private static final Map<String, String> DEFAULTS =
141         new HashMap<String, String>();
142 
143     static {
144         DEFAULTS.put(AbstractTilesApplicationContextFactory.APPLICATION_CONTEXT_FACTORY_INIT_PARAM,
145                 ChainedTilesApplicationContextFactory.class.getName());
146         DEFAULTS.put(REQUEST_CONTEXT_FACTORY_INIT_PARAM,
147                 ChainedTilesRequestContextFactory.class.getName());
148         DEFAULTS.put(DEFINITIONS_FACTORY_INIT_PARAM, UrlDefinitionsFactory.class.getName());
149         DEFAULTS.put(PREPARER_FACTORY_INIT_PARAM, BasicPreparerFactory.class.getName());
150         DEFAULTS.put(RENDERER_FACTORY_INIT_PARAM, BasicRendererFactory.class.getName());
151         DEFAULTS.put(ATTRIBUTE_EVALUATOR_INIT_PARAM, DirectAttributeEvaluator.class.getName());
152     }
153 
154     /***
155      * The default configuration to be used by the factory.
156      */
157     protected Map<String, String> defaultConfiguration =
158         new HashMap<String, String>(DEFAULTS);
159 
160     /***
161      * Retrieve a factory instance as configured through the specified context.
162      * <p/> The context will be queried and if a init parameter named
163      * 'org.apache.tiles.factory.TilesContainerFactory' is discovered this class
164      * will be instantiated and returned. Otherwise, the factory will attempt to
165      * utilize one of it's internal factories.
166      *
167      * @param context the executing applications context. Typically a
168      * ServletContext or PortletContext
169      * @return a tiles container
170      * @throws TilesContainerFactoryException if an error occurs creating the
171      * factory.
172      * @since 2.1.0
173      * @deprecated Use
174      * {@link AbstractTilesContainerFactory#getTilesContainerFactory(TilesApplicationContext)}.
175      */
176     @Deprecated
177     public static TilesContainerFactory getFactory(Object context) {
178         return getFactory(context, DEFAULTS);
179     }
180 
181     /***
182      * Retrieve a factory instance as configured through the specified context.
183      * <p/> The context will be queried and if a init parameter named
184      * 'org.apache.tiles.factory.TilesContainerFactory' is discovered this class
185      * will be instantiated and returned. Otherwise, the factory will attempt to
186      * utilize one of it's internal factories.
187      *
188      * @param context the executing applications context. Typically a
189      * ServletContext or PortletContext
190      * @param defaults Default configuration parameters values, used if the
191      * context object has not the corresponding parameters.
192      * @return a tiles container
193      * @throws TilesContainerFactoryException if an error occurs creating the
194      * factory.
195      * @deprecated Use
196      * {@link AbstractTilesContainerFactory#getTilesContainerFactory(TilesApplicationContext)}
197      * and then {@link #setDefaultConfiguration(Map)}.
198      */
199     public static TilesContainerFactory getFactory(Object context,
200             Map<String, String> defaults) {
201         Map<String, String> configuration = new HashMap<String, String>(defaults);
202         configuration.putAll(TilesContainerFactory.getInitParameterMap(context));
203         TilesContainerFactory factory =
204             (TilesContainerFactory) TilesContainerFactory.createFactory(configuration,
205                 CONTAINER_FACTORY_INIT_PARAM);
206         factory.setDefaultConfiguration(defaults);
207         return factory;
208     }
209 
210     /***
211      * Creates a Tiles container.
212      *
213      * @param context The (application) context object.
214      * @return The created container.
215      * @throws TilesContainerFactoryException If something goes wrong during
216      * instantiation.
217      * @deprecated Use {@link #createContainer(TilesApplicationContext)}.
218      */
219     @Deprecated
220     public TilesContainer createContainer(Object context) {
221         if (context instanceof TilesApplicationContext) {
222             return createContainer((TilesApplicationContext) context);
223         }
224 
225         throw new UnsupportedOperationException("Class "
226                 + context.getClass().getName()
227                 + " not recognized a TilesApplicationContext");
228     }
229 
230     /*** {@inheritDoc} */
231     public TilesContainer createContainer(TilesApplicationContext context) {
232         String value = context.getInitParams().get(
233                 CONTAINER_FACTORY_MUTABLE_INIT_PARAM);
234         if (Boolean.parseBoolean(value)) {
235             return createMutableTilesContainer(context);
236         } else {
237             return createTilesContainer(context);
238         }
239     }
240 
241     /***
242      * Sets the default configuration parameters.
243      *
244      * @param defaultConfiguration The default configuration parameters.
245      */
246     public void setDefaultConfiguration(Map<String, String> defaultConfiguration) {
247         if (defaultConfiguration != null) {
248             this.defaultConfiguration.putAll(defaultConfiguration);
249         }
250     }
251 
252     /***
253      * Sets one default configuration parameter value.
254      *
255      * @param key The key of the configuration parameter.
256      * @param value The value of the configuration parameter.
257      */
258     public void setDefaultValue(String key, String value) {
259         this.defaultConfiguration.put(key, value);
260     }
261 
262     /***
263      * Creates an immutable Tiles container.
264      *
265      * @param context The (application) context object.
266      * @return The created Tiles container.
267      * @throws TilesContainerFactoryException If something goes wrong during
268      * initialization.
269      * @deprecated Use {@link #createTilesContainer(TilesApplicationContext)}.
270      */
271     @Deprecated
272     public TilesContainer createTilesContainer(Object context) {
273         if (context instanceof TilesApplicationContext) {
274             return createTilesContainer((TilesApplicationContext) context);
275         }
276 
277         throw new UnsupportedOperationException("Class "
278                 + context.getClass().getName()
279                 + " not recognized a TilesApplicationContext");
280     }
281 
282     /***
283      * Creates an immutable Tiles container.
284      *
285      * @param context The Tiles application context object.
286      * @return The created Tiles container.
287      * @throws TilesContainerFactoryException If something goes wrong during
288      * initialization.
289      * @since 2.1.1
290      */
291     public TilesContainer createTilesContainer(TilesApplicationContext context) {
292         BasicTilesContainer container = new BasicTilesContainer();
293         initializeContainer(context, container);
294         return container;
295     }
296 
297     /***
298      * Creates an immutable Tiles container.
299      *
300      * @param context The (application) context object.
301      * @return The created Tiles container.
302      * @throws TilesContainerFactoryException If something goes wrong during
303      * initialization.
304      * @deprecated Use
305      * {@link #createMutableTilesContainer(TilesApplicationContext)}.
306      */
307     @Deprecated
308     public TilesContainer createMutableTilesContainer(Object context) {
309         if (context instanceof TilesApplicationContext) {
310             return createMutableTilesContainer((TilesApplicationContext) context);
311         }
312 
313         throw new UnsupportedOperationException("Class "
314                 + context.getClass().getName()
315                 + " not recognized a TilesApplicationContext");
316     }
317 
318     /***
319      * Creates a mutable Tiles container.
320      *
321      * @param context The Tiles application context object.
322      * @return The created Tiles container.
323      * @throws TilesContainerFactoryException If something goes wrong during
324      * initialization.
325      */
326     public MutableTilesContainer createMutableTilesContainer(
327             TilesApplicationContext context) {
328         CachingTilesContainer container = new CachingTilesContainer();
329         initializeContainer(context, container);
330         return container;
331     }
332 
333     /***
334      * Initializes a container.
335      *
336      * @param context The (application) context object to use.
337      * @param container The container to be initialized.
338      * @throws TilesContainerFactoryException If something goes wrong during
339      * initialization.
340      * @deprecated Use
341      * {@link #initializeContainer(TilesApplicationContext, BasicTilesContainer)}.
342      */
343     @Deprecated
344     protected void initializeContainer(Object context,
345             BasicTilesContainer container) {
346         if (context instanceof TilesApplicationContext) {
347             initializeContainer((TilesApplicationContext) context, container);
348         }
349 
350         throw new UnsupportedOperationException("Class "
351                 + context.getClass().getName()
352                 + " not recognized a TilesApplicationContext");
353     }
354 
355     /***
356      * Initializes a container.
357      *
358      * @param context The Tiles application context object to use.
359      * @param container The container to be initialized.
360      * @throws TilesContainerFactoryException If something goes wrong during
361      * initialization.
362      */
363     protected void initializeContainer(TilesApplicationContext context,
364             BasicTilesContainer container) {
365         log.warn("DEPRECATION WARNING! You are using parameter-based initialization, "
366                 + "that is no longer supported! Please see docs: "
367                 + "http://tiles.apache.org/framework/tutorial/configuration.html");
368 
369         Map <String, String> initParameterMap;
370 
371         if (log.isInfoEnabled()) {
372             log.info("Initializing Tiles2 container. . .");
373         }
374 
375         initParameterMap = context.getInitParams();
376         Map<String, String> configuration = new HashMap<String, String>(defaultConfiguration);
377         configuration.putAll(initParameterMap);
378         storeContainerDependencies(context, initParameterMap, configuration, container);
379         container.init(initParameterMap);
380 
381         if (log.isInfoEnabled()) {
382             log.info("Tiles2 container initialized");
383         }
384     }
385 
386     /***
387      * Stores container dependencies, that is called before
388      * {@link TilesContainer#init(Map)}.
389      *
390      * @param context The (application) context object to use.
391      * @param initParameters The initialization parameters.
392      * @param configuration The merged configuration parameters (both defaults
393      * and context ones).
394      * @param container The container to use.
395      * @throws TilesContainerFactoryException If something goes wrong during
396      * initialization.
397      * @deprecated Use
398      * {@link #storeContainerDependencies(TilesApplicationContext, Map, Map, BasicTilesContainer)}
399      * .
400      */
401     protected void storeContainerDependencies(Object context,
402             Map<String, String> initParameters,
403             Map<String, String> configuration, BasicTilesContainer container) {
404         if (context instanceof TilesApplicationContext) {
405             storeContainerDependencies((TilesApplicationContext) context,
406                     initParameters, configuration, container);
407         }
408 
409         throw new UnsupportedOperationException("Class "
410                 + context.getClass().getName()
411                 + " not recognized a TilesApplicationContext");
412     }
413 
414     /***
415      * Stores container dependencies, that is called before
416      * {@link TilesContainer#init(Map)}.
417      *
418      * @param context The (application) context object to use.
419      * @param initParameters The initialization parameters.
420      * @param configuration The merged configuration parameters (both defaults
421      * and context ones).
422      * @param container The container to use.
423      * @throws TilesContainerFactoryException If something goes wrong during
424      * initialization.
425      */
426     protected void storeContainerDependencies(TilesApplicationContext context,
427             Map<String, String> initParameters,
428             Map<String, String> configuration, BasicTilesContainer container) {
429         AbstractTilesApplicationContextFactory contextFactory =
430             (AbstractTilesApplicationContextFactory) createFactory(configuration,
431                 AbstractTilesApplicationContextFactory.APPLICATION_CONTEXT_FACTORY_INIT_PARAM);
432         if (contextFactory instanceof Initializable) {
433             ((Initializable) contextFactory).init(configuration);
434         }
435 
436         TilesRequestContextFactory requestContextFactory =
437             (TilesRequestContextFactory) createFactory(configuration,
438                 REQUEST_CONTEXT_FACTORY_INIT_PARAM);
439         requestContextFactory.init(configuration);
440 
441         RendererFactory rendererFactory =
442             (RendererFactory) createFactory(configuration,
443                 RENDERER_FACTORY_INIT_PARAM);
444 
445         AttributeEvaluator evaluator = (AttributeEvaluator) createFactory(
446                 configuration, ATTRIBUTE_EVALUATOR_INIT_PARAM);
447         AttributeEvaluatorFactory attributeEvaluatorFactory = new BasicAttributeEvaluatorFactory(
448                 evaluator);
449 
450         if (evaluator instanceof TilesApplicationContextAware) {
451             ((TilesApplicationContextAware) evaluator)
452                     .setApplicationContext(context);
453         }
454 
455         if (evaluator instanceof TilesContainerAware) {
456             ((TilesContainerAware) evaluator).setContainer(container);
457         }
458 
459         evaluator.init(configuration);
460 
461         if (rendererFactory instanceof TilesRequestContextFactoryAware) {
462             ((TilesRequestContextFactoryAware) rendererFactory)
463                     .setRequestContextFactory(requestContextFactory);
464         }
465 
466         if (rendererFactory instanceof TilesApplicationContextAware) {
467             ((TilesApplicationContextAware) rendererFactory)
468                     .setApplicationContext(context);
469         }
470 
471         if (rendererFactory instanceof TilesContainerAware) {
472             ((TilesContainerAware) rendererFactory).setContainer(container);
473         }
474 
475         if (rendererFactory instanceof AttributeEvaluatorFactoryAware) {
476             ((AttributeEvaluatorFactoryAware) rendererFactory)
477                     .setAttributeEvaluatorFactory(attributeEvaluatorFactory);
478         }
479         rendererFactory.init(initParameters);
480 
481         PreparerFactory prepFactory =
482             (PreparerFactory) createFactory(configuration,
483                 PREPARER_FACTORY_INIT_PARAM);
484 
485         postCreationOperations(requestContextFactory, context, rendererFactory,
486                 evaluator, initParameters, configuration, container);
487 
488         container.setRequestContextFactory(requestContextFactory);
489         container.setPreparerFactory(prepFactory);
490         container.setApplicationContext(context);
491         container.setRendererFactory(rendererFactory);
492         container.setAttributeEvaluatorFactory(attributeEvaluatorFactory);
493     }
494 
495     /***
496      * After the creation of the elements, it is possible to do other operations that
497      * will be done after the creation and before the assignment to the container.
498      *
499      * @param contextFactory The Tiles context factory.
500      * @param tilesContext The Tiles application context.
501      * @param rendererFactory The renderer factory.
502      * @param evaluator The attribute evaluator.
503      * @param initParameters The initialization parameters.
504      * @param configuration The merged configuration parameters (both defaults
505      * and context ones).
506      * @param container The container to use.
507      * @since 2.1.1
508      */
509     protected void postCreationOperations(TilesRequestContextFactory contextFactory,
510             TilesApplicationContext tilesContext,
511             RendererFactory rendererFactory, AttributeEvaluator evaluator,
512             Map<String, String> initParameters,
513             Map<String, String> configuration, BasicTilesContainer container) {
514         DefinitionsFactory defsFactory =
515             (DefinitionsFactory) createFactory(configuration,
516                 DEFINITIONS_FACTORY_INIT_PARAM);
517         if (defsFactory instanceof TilesApplicationContextAware) {
518             ((TilesApplicationContextAware) defsFactory)
519                     .setApplicationContext(tilesContext);
520         }
521 
522         defsFactory.init(configuration);
523 
524         container.setDefinitionsFactory(defsFactory);
525     }
526 
527     /***
528      * Creates a factory instance.
529      *
530      * @param configuration The merged configuration parameters (both defaults
531      * and context ones).
532      * @param initParameterName The initialization parameter name from which the
533      * class name is got.
534      * @return The created factory.
535      * @throws TilesContainerFactoryException If something goes wrong during
536      * creation.
537      */
538     protected static Object createFactory(Map<String, String> configuration,
539             String initParameterName) {
540         String factoryName = resolveFactoryName(configuration, initParameterName);
541         return ClassUtil.instantiate(factoryName);
542     }
543 
544     /***
545      * Resolves a factory class name.
546      *
547      * @param configuration The merged configuration parameters (both defaults
548      * and context ones).
549      * @param parameterName The name of the initialization parameter to use.
550      * @return The factory class name.
551      * @throws TilesContainerFactoryException If something goes wrong during
552      * resolution.
553      */
554     protected static String resolveFactoryName(
555             Map<String, String> configuration, String parameterName) {
556         Object factoryName = configuration.get(parameterName);
557         return factoryName == null
558             ? DEFAULTS.get(parameterName)
559             : factoryName.toString();
560     }
561     /***
562      * Returns the value of an initialization parameter.
563      *
564      * @param context The (application) context object to use.
565      * @param parameterName The parameter name to retrieve.
566      * @return The parameter value.
567      * @throws TilesContainerFactoryException If the context has not been
568      * recognized.
569      * @deprecated Do not use.
570      */
571     @Deprecated
572     protected static String getInitParameter(Object context,
573             String parameterName) {
574         Object value;
575         Class<?> contextClass = context.getClass();
576         Method getInitParameterMethod = ClassUtil
577                 .getForcedAccessibleMethod(contextClass,
578                         "getInitParameter", String.class);
579         value = ClassUtil.invokeMethod(context, getInitParameterMethod,
580                 parameterName);
581 
582         return value == null ? null : value.toString();
583     }
584 
585 
586     /***
587      * Returns a map containing parameters name-value entries.
588      *
589      * @param context The (application) context object to use.
590      * @return The initialization parameters map.
591      * @throws TilesContainerFactoryException If the context object has not been
592      * recognized.
593      * @deprecated Do not use.
594      */
595     @Deprecated
596     @SuppressWarnings("unchecked")
597     protected static Map<String, String> getInitParameterMap(Object context) {
598         Map<String, String> initParameters = new HashMap<String, String>();
599         Class<?> contextClass = context.getClass();
600         Method method = ClassUtil.getForcedAccessibleMethod(contextClass,
601                 "getInitParameterNames");
602         Enumeration<String> e = (Enumeration<String>) ClassUtil
603                 .invokeMethod(context, method);
604 
605         method = ClassUtil.getForcedAccessibleMethod(contextClass,
606                 "getInitParameter", String.class);
607         while (e.hasMoreElements()) {
608             String key = e.nextElement();
609             initParameters.put(key, (String) ClassUtil.invokeMethod(
610                     context, method, key));
611         }
612 
613         return initParameters;
614     }
615 }