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.struts.tiles;
23
24 import java.util.Map;
25
26 import jakarta.servlet.ServletContext;
27 import jakarta.servlet.ServletException;
28 import jakarta.servlet.UnavailableException;
29
30 import org.apache.struts.action.ActionServlet;
31 import org.apache.struts.action.PlugIn;
32 import org.apache.struts.action.RequestProcessor;
33 import org.apache.struts.chain.ComposableRequestProcessor;
34 import org.apache.struts.config.ControllerConfig;
35 import org.apache.struts.config.ModuleConfig;
36 import org.apache.struts.config.PlugInConfig;
37 import org.apache.struts.util.RequestUtils;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40 import org.slf4j.Marker;
41 import org.slf4j.MarkerFactory;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 public class TilesPlugin implements PlugIn {
67
68
69
70
71 private final static Marker FATAL = MarkerFactory.getMarker("FATAL");
72
73
74
75
76 private final Logger log =
77 LoggerFactory.getLogger(TilesPlugin.class);
78
79
80
81
82 protected boolean moduleAware = false;
83
84
85
86
87
88 protected String tilesUtilImplClassname = null;
89
90
91
92
93 protected DefinitionsFactory definitionFactory = null;
94
95
96
97
98
99 protected PlugInConfig currentPlugInConfigObject=null;
100
101
102
103
104
105
106 public boolean isModuleAware() {
107 return moduleAware;
108 }
109
110
111
112
113
114
115
116
117 public void setModuleAware(boolean moduleAware) {
118 this.moduleAware = moduleAware;
119 }
120
121
122
123
124
125
126
127
128
129
130
131
132
133 public void init(ActionServlet servlet, ModuleConfig moduleConfig)
134 throws ServletException {
135
136
137 DefinitionsFactoryConfig factoryConfig =
138 readFactoryConfig(servlet, moduleConfig);
139
140
141
142 factoryConfig.setFactoryName(moduleConfig.getPrefix());
143
144
145 this.initRequestProcessorClass(moduleConfig);
146
147 this.initTilesUtil();
148
149 this.initDefinitionsFactory(servlet.getServletContext(), moduleConfig, factoryConfig);
150 }
151
152
153
154
155
156
157
158
159 private void initTilesUtil() throws ServletException {
160
161 if (TilesUtil.isTilesUtilImplSet()) {
162 log.debug("Skipping re-init of Tiles Plugin. Values defined in the " +
163 "first initialized plugin take precedence.");
164 return;
165 }
166
167
168
169
170
171 if (this.getTilesUtilImplClassname() == null) {
172
173 if (isModuleAware()) {
174 TilesUtil.setTilesUtil(new TilesUtilStrutsModulesImpl());
175 } else {
176 TilesUtil.setTilesUtil(new TilesUtilStrutsImpl());
177 }
178
179 } else {
180 try {
181 TilesUtilStrutsImpl impl =
182 (TilesUtilStrutsImpl) RequestUtils
183 .applicationClass(getTilesUtilImplClassname())
184 .getDeclaredConstructor().newInstance();
185 TilesUtil.setTilesUtil(impl);
186
187 } catch (ClassCastException ex) {
188 throw new ServletException(
189 "Can't set TilesUtil implementation to '"
190 + getTilesUtilImplClassname()
191 + "'. TilesUtil implementation should be a subclass of '"
192 + TilesUtilStrutsImpl.class.getName()
193 + "'", ex);
194
195 } catch (Exception ex) {
196 throw new ServletException(
197 "Can't set TilesUtil implementation.",
198 ex);
199 }
200 }
201
202 }
203
204
205
206
207
208
209
210
211 private void initDefinitionsFactory(
212 ServletContext servletContext,
213 ModuleConfig moduleConfig,
214 DefinitionsFactoryConfig factoryConfig)
215 throws ServletException {
216
217
218 definitionFactory =
219 ((TilesUtilStrutsImpl) TilesUtil.getTilesUtil()).getDefinitionsFactory(
220 servletContext,
221 moduleConfig);
222
223 if (definitionFactory != null) {
224 throw new UnavailableException(
225 "Factory already exists for module '"
226 + moduleConfig.getPrefix()
227 + "' and cannot be redefined. " +
228 "The factory found is from module '"
229 + definitionFactory.getConfig().getFactoryName() + "'.");
230 }
231
232
233 try {
234 definitionFactory =
235 TilesUtil.createDefinitionsFactory(
236 servletContext,
237 factoryConfig);
238
239 } catch (DefinitionsFactoryException ex) {
240 log.error("Can't create Tiles definition factory for module '{}'.",
241 moduleConfig.getPrefix());
242
243 throw new ServletException(ex);
244 }
245
246 log.info("Tiles definition factory loaded for module '{}'.",
247 moduleConfig.getPrefix());
248 }
249
250
251
252
253 public void destroy() {
254 definitionFactory.destroy();
255 definitionFactory = null;
256 }
257
258
259
260
261
262
263
264
265
266
267
268 @SuppressWarnings("deprecation")
269 protected DefinitionsFactoryConfig readFactoryConfig(
270 ActionServlet servlet,
271 ModuleConfig config)
272 throws ServletException {
273
274
275 DefinitionsFactoryConfig factoryConfig = new DefinitionsFactoryConfig();
276
277 try {
278 DefinitionsUtil.populateDefinitionsFactoryConfig(
279 factoryConfig,
280 servlet.getServletConfig());
281
282 } catch (Exception ex) {
283 String message = "Can't populate DefinitionsFactoryConfig class from 'web.xml'";
284 log.debug(message, ex);
285 ex.printStackTrace();
286 UnavailableException e2 = new UnavailableException(message);
287 e2.initCause(ex);
288 throw e2;
289 }
290
291
292 try {
293 Map<String, Object> strutsProperties = findStrutsPlugInConfigProperties(servlet, config);
294 factoryConfig.populate(strutsProperties);
295
296 } catch (Exception ex) {
297 String message = "Can't populate DefinitionsFactoryConfig class from '"
298 + config.getPrefix()
299 + "/struts-config.xml'";
300
301 log.debug(message, ex);
302
303 UnavailableException e2 = new UnavailableException(message);
304 e2.initCause(ex);
305 throw e2;
306 }
307
308 return factoryConfig;
309 }
310
311
312
313
314
315
316
317
318
319
320
321
322
323 protected Map<String, Object> findStrutsPlugInConfigProperties(
324 ActionServlet servlet,
325 ModuleConfig config)
326 throws ServletException {
327
328 return currentPlugInConfigObject.getProperties();
329 }
330
331
332
333
334
335
336
337
338
339
340
341 protected void initRequestProcessorClass(ModuleConfig config)
342 throws ServletException {
343
344 String tilesProcessorClassname = TilesRequestProcessor.class.getName();
345 ControllerConfig ctrlConfig = config.getControllerConfig();
346 String configProcessorClassname = ctrlConfig.getProcessorClass();
347
348
349 Class<?> configProcessorClass;
350 try {
351 configProcessorClass =
352 RequestUtils.applicationClass(configProcessorClassname);
353
354 } catch (ClassNotFoundException ex) {
355 log.error(FATAL, "Can't set TilesRequestProcessor: bad class name '{}'.",
356 configProcessorClassname);
357 throw new ServletException(ex);
358 }
359
360
361
362 if (ComposableRequestProcessor.class.isAssignableFrom(configProcessorClass)) {
363 return;
364 }
365
366
367
368 if (configProcessorClassname.equals(RequestProcessor.class.getName())
369 || configProcessorClassname.endsWith(tilesProcessorClassname)) {
370
371 ctrlConfig.setProcessorClass(tilesProcessorClassname);
372 return;
373 }
374
375
376 Class<?> tilesProcessorClass = TilesRequestProcessor.class;
377 if (!tilesProcessorClass.isAssignableFrom(configProcessorClass)) {
378
379 String msg =
380 "TilesPlugin : Specified RequestProcessor not compatible with TilesRequestProcessor";
381 log.error(FATAL, msg);
382 throw new ServletException(msg);
383 }
384 }
385
386
387
388
389
390
391 public void setTilesUtilImplClassname(String tilesUtilImplClassname) {
392 this.tilesUtilImplClassname = tilesUtilImplClassname;
393 }
394
395
396
397
398
399 public String getTilesUtilImplClassname() {
400 return tilesUtilImplClassname;
401 }
402
403
404
405
406
407
408 public void setCurrentPlugInConfigObject(PlugInConfig plugInConfigObject) {
409 this.currentPlugInConfigObject = plugInConfigObject;
410 }
411 }