View Javadoc

1   /*
2    * $Id: TilesContainerFactory.java 680124 2008-07-27 15:20:00Z 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 org.apache.tiles.TilesApplicationContext;
24  import org.apache.tiles.TilesContainer;
25  import org.apache.tiles.TilesException;
26  import org.apache.tiles.context.ChainedTilesContextFactory;
27  import org.apache.tiles.context.TilesContextFactory;
28  import org.apache.tiles.definition.DefinitionsFactory;
29  import org.apache.tiles.definition.UrlDefinitionsFactory;
30  import org.apache.tiles.impl.BasicTilesContainer;
31  import org.apache.tiles.impl.mgmt.CachingTilesContainer;
32  import org.apache.tiles.mgmt.MutableTilesContainer;
33  import org.apache.tiles.preparer.BasicPreparerFactory;
34  import org.apache.tiles.preparer.PreparerFactory;
35  import org.apache.tiles.reflect.ClassUtil;
36  
37  import java.lang.reflect.Method;
38  import java.util.Enumeration;
39  import java.util.HashMap;
40  import java.util.Map;
41  
42  /***
43   * Factory provided for convenience.
44   * This factory creates a default implementation of
45   * the container, initializes, and puts it into service.
46   *
47   * @version $Rev: 680124 $ $Date: 2008-07-27 17:20:00 +0200 (Sun, 27 Jul 2008) $
48   * @since 2.0
49   */
50  public class TilesContainerFactory {
51  
52      /***
53       * Initialization parameter that represents the container factory class
54       * name.
55       */
56      public static final String CONTAINER_FACTORY_INIT_PARAM =
57          "org.apache.tiles.factory.TilesContainerFactory";
58  
59      /***
60       * Initialization parameter that indicates if the container factory is
61       * mutable.
62       */
63      public static final String CONTAINER_FACTORY_MUTABLE_INIT_PARAM =
64          "org.apache.tiles.factory.TilesContainerFactory.MUTABLE";
65  
66      /***
67       * Initialization parameter that represents the context factory class name.
68       */
69      public static final String CONTEXT_FACTORY_INIT_PARAM =
70          "org.apache.tiles.context.TilesContextFactory";
71  
72      /***
73       * Initialization parameter that represents the definitions factory class
74       * name.
75       */
76      public static final String DEFINITIONS_FACTORY_INIT_PARAM =
77          "org.apache.tiles.definition.DefinitionsFactory";
78  
79      /***
80       * Initialization parameter that represents the preparer factory class name.
81       */
82      public static final String PREPARER_FACTORY_INIT_PARAM =
83          "org.apache.tiles.preparer.PreparerFactory";
84  
85  
86      /***
87       * Default configuration parameters.
88       */
89      private static final Map<String, String> DEFAULTS =
90          new HashMap<String, String>();
91  
92      static {
93          DEFAULTS.put(CONTAINER_FACTORY_INIT_PARAM, TilesContainerFactory.class.getName());
94          DEFAULTS.put(CONTEXT_FACTORY_INIT_PARAM, ChainedTilesContextFactory.class.getName());
95          DEFAULTS.put(DEFINITIONS_FACTORY_INIT_PARAM, UrlDefinitionsFactory.class.getName());
96          DEFAULTS.put(PREPARER_FACTORY_INIT_PARAM, BasicPreparerFactory.class.getName());
97      }
98  
99      /***
100      * The default configuration to be used by the factory.
101      */
102     protected Map<String, String> defaultConfiguration =
103         new HashMap<String, String>(DEFAULTS);
104 
105     /***
106      * Retrieve a factory instance as configured through the
107      * specified context.
108      * <p/>
109      * The context will be queried and if a init parameter
110      * named 'org.apache.tiles.factory.TilesContainerFactory' is discovered
111      * this class will be instantiated and returned. Otherwise,
112      * the factory will attempt to utilize one of it's internal
113      * factories.
114      *
115      * @param context the executing applications context.
116      *                Typically a ServletContext or PortletContext
117      * @return a tiles container
118      * @throws TilesException if an error occurs creating the factory.
119      */
120     public static TilesContainerFactory getFactory(Object context)
121         throws TilesException {
122         return getFactory(context, DEFAULTS);
123     }
124 
125     /***
126      * Retrieve a factory instance as configured through the specified context.
127      * <p/> The context will be queried and if a init parameter named
128      * 'org.apache.tiles.factory.TilesContainerFactory' is discovered this class
129      * will be instantiated and returned. Otherwise, the factory will attempt to
130      * utilize one of it's internal factories.
131      *
132      * @param context the executing applications context. Typically a
133      * ServletContext or PortletContext
134      * @param defaults Default configuration parameters values, used if the
135      * context object has not the corresponding parameters.
136      * @return a tiles container
137      * @throws TilesException if an error occurs creating the factory.
138      */
139     public static TilesContainerFactory getFactory(Object context,
140                                                    Map<String, String> defaults)
141         throws TilesException {
142         Map<String, String> configuration = new HashMap<String, String>(defaults);
143         configuration.putAll(getInitParameterMap(context));
144         TilesContainerFactory factory =
145             (TilesContainerFactory) TilesContainerFactory.createFactory(configuration,
146                 CONTAINER_FACTORY_INIT_PARAM);
147         factory.setDefaultConfiguration(defaults);
148         return factory;
149     }
150 
151     /***
152      * Creates a Tiles container.
153      *
154      * @param context The (application) context object.
155      * @return The created container.
156      * @throws TilesException If something goes wrong during instantiation.
157      */
158     public TilesContainer createContainer(Object context) throws TilesException {
159         String value = getInitParameter(context, CONTAINER_FACTORY_MUTABLE_INIT_PARAM);
160         if (Boolean.parseBoolean(value)) {
161             return createMutableTilesContainer(context);
162         } else {
163             return createTilesContainer(context);
164         }
165     }
166 
167     /***
168      * Sets the default configuration parameters.
169      *
170      * @param defaultConfiguration The default configuration parameters.
171      */
172     public void setDefaultConfiguration(Map<String, String> defaultConfiguration) {
173         if (defaultConfiguration != null) {
174             this.defaultConfiguration.putAll(defaultConfiguration);
175         }
176     }
177 
178     /***
179      * Sets one default configuration parameter value.
180      *
181      * @param key The key of the configuration parameter.
182      * @param value The value of the configuration parameter.
183      */
184     public void setDefaultValue(String key, String value) {
185         this.defaultConfiguration.put(key, value);
186     }
187 
188     /***
189      * Creates an immutable Tiles container.
190      *
191      * @param context The (application) context object.
192      * @return The created Tiles container.
193      * @throws TilesException If something goes wrong during initialization.
194      */
195     public TilesContainer createTilesContainer(Object context)
196         throws TilesException {
197         BasicTilesContainer container = new BasicTilesContainer();
198         initializeContainer(context, container);
199         return container;
200     }
201 
202     /***
203      * Creates a mutable Tiles container.
204      *
205      * @param context The (application) context object.
206      * @return The created Tiles container.
207      * @throws TilesException If something goes wrong during initialization.
208      */
209     public MutableTilesContainer createMutableTilesContainer(Object context)
210         throws TilesException {
211         CachingTilesContainer container = new CachingTilesContainer();
212         initializeContainer(context, container);
213         return container;
214     }
215 
216     /***
217      * Initializes a container.
218      *
219      * @param context The (application) context object to use.
220      * @param container The container to be initialized.
221      * @throws TilesException If something goes wrong during initialization.
222      */
223     protected void initializeContainer(Object context,
224                                        BasicTilesContainer container)
225         throws TilesException {
226         Map <String, String> initParameterMap;
227 
228         initParameterMap = getInitParameterMap(context);
229         Map<String, String> configuration = new HashMap<String, String>(defaultConfiguration);
230         configuration.putAll(initParameterMap);
231         storeContainerDependencies(context, initParameterMap, configuration, container);
232         container.init(initParameterMap);
233     }
234 
235     /***
236      * Stores container dependencies, that is called before
237      * {@link TilesContainer#init(Map)}.
238      *
239      * @param context The (application) context object to use.
240      * @param initParameters The initialization parameters.
241      * @param configuration The merged configuration parameters (both defaults
242      * and context ones).
243      * @param container The container to use.
244      * @throws TilesException If something goes wrong during initialization.
245      */
246     protected void storeContainerDependencies(Object context,
247                                               Map<String, String> initParameters,
248                                               Map<String, String> configuration,
249                                               BasicTilesContainer container) throws TilesException {
250         TilesContextFactory contextFactory =
251             (TilesContextFactory) createFactory(configuration,
252                 CONTEXT_FACTORY_INIT_PARAM);
253 
254         DefinitionsFactory defsFactory =
255             (DefinitionsFactory) createFactory(configuration,
256                 DEFINITIONS_FACTORY_INIT_PARAM);
257 
258         PreparerFactory prepFactory =
259             (PreparerFactory) createFactory(configuration,
260                 PREPARER_FACTORY_INIT_PARAM);
261 
262         contextFactory.init(configuration);
263         TilesApplicationContext tilesContext =
264             contextFactory.createApplicationContext(context);
265 
266         container.setDefinitionsFactory(defsFactory);
267         container.setContextFactory(contextFactory);
268         container.setPreparerFactory(prepFactory);
269         container.setApplicationContext(tilesContext);
270     }
271 
272 
273     /***
274      * Creates a factory instance.
275      *
276      * @param configuration The merged configuration parameters (both defaults
277      * and context ones).
278      * @param initParameterName The initialization parameter name from which the
279      * class name is got.
280      * @return The created factory.
281      * @throws TilesException If something goes wrong during creation.
282      */
283     protected static Object createFactory(Map<String, String> configuration, String initParameterName)
284         throws TilesException {
285         String factoryName = resolveFactoryName(configuration, initParameterName);
286         return ClassUtil.instantiate(factoryName);
287     }
288 
289     /***
290      * Resolves a factory class name.
291      *
292      * @param configuration The merged configuration parameters (both defaults
293      * and context ones).
294      * @param parameterName The name of the initialization parameter to use.
295      * @return The factory class name.
296      * @throws TilesException If something goes wrong during resolution.
297      */
298     protected static String resolveFactoryName(Map<String, String> configuration, String parameterName)
299         throws TilesException {
300         Object factoryName = configuration.get(parameterName);
301         return factoryName == null
302             ? DEFAULTS.get(parameterName)
303             : factoryName.toString();
304     }
305 
306     /***
307      * Returns the value of an initialization parameter.
308      *
309      * @param context The (application) context object to use.
310      * @param parameterName The parameter name to retrieve.
311      * @return The parameter value.
312      * @throws TilesException If the context has not been recognized.
313      */
314     protected static String getInitParameter(Object context,
315                                              String parameterName) throws TilesException {
316         Object value;
317         try {
318             Class<?> contextClass = context.getClass();
319             Method getInitParameterMethod =
320                 contextClass.getMethod("getInitParameter", String.class);
321             value = getInitParameterMethod.invoke(context, parameterName);
322         } catch (Exception e) {
323             throw new TilesException("Unrecognized context.  Is this context"
324                     + " a ServletContext, PortletContext, or similar?", e);
325         }
326         return value == null ? null : value.toString();
327     }
328 
329     /***
330      * Returns a map containing parameters name-value entries.
331      *
332      * @param context The (application) context object to use.
333      * @return The initialization parameters map.
334      * @throws TilesException If the context object has not been recognized.
335      */
336     @SuppressWarnings("unchecked")
337     protected static Map<String, String> getInitParameterMap(Object context)
338         throws TilesException {
339         Map<String, String> initParameters = new HashMap<String, String>();
340         Class<?> contextClass = context.getClass();
341         try {
342             Method method = contextClass.getMethod("getInitParameterNames");
343             Enumeration<String> e = (Enumeration<String>) method
344                     .invoke(context);
345 
346             method = contextClass.getMethod("getInitParameter", String.class);
347             while (e.hasMoreElements()) {
348                 String key = e.nextElement();
349                 initParameters.put(key, (String) method.invoke(context, key));
350             }
351         } catch (Exception e) {
352             throw new TilesException("Unable to retrieve init parameters."
353                     + " Is this context a ServletContext, PortletContext,"
354                     + " or similar object?", e);
355         }
356         return initParameters;
357     }
358 
359 
360 }