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