%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.turbine.services.pull.util.UIManager |
|
|
1 | package org.apache.turbine.services.pull.util; |
|
2 | ||
3 | /* |
|
4 | * Copyright 2001-2005 The Apache Software Foundation. |
|
5 | * |
|
6 | * Licensed under the Apache License, Version 2.0 (the "License") |
|
7 | * you may not use this file except in compliance with the License. |
|
8 | * You may obtain a copy of the License at |
|
9 | * |
|
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
11 | * |
|
12 | * Unless required by applicable law or agreed to in writing, software |
|
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
15 | * See the License for the specific language governing permissions and |
|
16 | * limitations under the License. |
|
17 | */ |
|
18 | ||
19 | import java.io.InputStream; |
|
20 | import java.util.Properties; |
|
21 | ||
22 | import org.apache.commons.configuration.Configuration; |
|
23 | import org.apache.commons.lang.StringUtils; |
|
24 | import org.apache.commons.logging.Log; |
|
25 | import org.apache.commons.logging.LogFactory; |
|
26 | import org.apache.turbine.Turbine; |
|
27 | import org.apache.turbine.om.security.User; |
|
28 | import org.apache.turbine.services.pull.ApplicationTool; |
|
29 | import org.apache.turbine.services.pull.TurbinePull; |
|
30 | import org.apache.turbine.services.servlet.TurbineServlet; |
|
31 | import org.apache.turbine.util.RunData; |
|
32 | import org.apache.turbine.util.ServerData; |
|
33 | import org.apache.turbine.util.uri.DataURI; |
|
34 | ||
35 | /** |
|
36 | * UIManager.java |
|
37 | * <br> |
|
38 | * Manages all UI elements for a Turbine Application. Any |
|
39 | * UI element can be accessed in any template using the |
|
40 | * $ui handle (assuming you use the default PullService |
|
41 | * configuration). So, for example, you could access |
|
42 | * the background colour for your pages by using |
|
43 | * $ui.bgcolor |
|
44 | * <p> |
|
45 | * <h3>Questions:</h3> |
|
46 | * What is the best way to allow an application |
|
47 | * to be skinned. And how to allow the flexible |
|
48 | * altering of a particular UI element in certain |
|
49 | * parts of the template hierarchy. For example |
|
50 | * on one section of your site you might like |
|
51 | * a certain bgcolor, on another part of your |
|
52 | * site you might want another. How can be let |
|
53 | * the designer specify these properties and |
|
54 | * still use the single $app.ui.bgcolor in |
|
55 | * all the templates. |
|
56 | * <p> |
|
57 | * It would also be very cool to use some form |
|
58 | * of inheritence for UI elements. Say a $ui.bgcolor |
|
59 | * is used in a template where the bgcolor is not |
|
60 | * set for that part of hierarch, it would be cool |
|
61 | * if it could find the setting for the bgcolor |
|
62 | * in the parent directory. So you could override |
|
63 | * a UI element where you wanted and the system |
|
64 | * would fall back to the parent when necessary. |
|
65 | * <p> |
|
66 | * How to specify skins, how to deal with images, |
|
67 | * how could this be handled with a web app. |
|
68 | * <p> |
|
69 | * |
|
70 | * This is an application pull tool for the template system. You should <b>not</b> |
|
71 | * use it in a normal application! |
|
72 | * |
|
73 | * |
|
74 | * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a> |
|
75 | * @author <a href="mailto:james_coltman@majorband.co.uk">James Coltman</a> |
|
76 | * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> |
|
77 | * @author <a href="thomas.vandahl@tewisoft.de">Thomas Vandahl</a> |
|
78 | * @version $Id: UIManager.java 290076 2005-09-19 07:13:51Z henning $ |
|
79 | */ |
|
80 | 52 | public class UIManager implements ApplicationTool |
81 | { |
|
82 | /** Logging */ |
|
83 | 52 | private static Log log = LogFactory.getLog(UIManager.class); |
84 | ||
85 | /** |
|
86 | * The location of the skins within the application |
|
87 | * resources directory. |
|
88 | */ |
|
89 | private static final String SKINS_DIRECTORY = "/ui/skins"; |
|
90 | ||
91 | /** |
|
92 | * The name of the directory where images are |
|
93 | * stored for this skin. |
|
94 | */ |
|
95 | private static final String IMAGES_DIRECTORY = "/images"; |
|
96 | ||
97 | /** |
|
98 | * Property tag for the default skin that is to be |
|
99 | * used for the web application. |
|
100 | */ |
|
101 | private static final String SKIN_PROPERTY = "tool.ui.skin"; |
|
102 | ||
103 | /** |
|
104 | * Property tag for the image directory inside the skin that is to be |
|
105 | * used for the web application. |
|
106 | */ |
|
107 | private static final String IMAGEDIR_PROPERTY = "tool.ui.dir.image"; |
|
108 | ||
109 | /** |
|
110 | * Property tag for the skin directory that is to be |
|
111 | * used for the web application. |
|
112 | */ |
|
113 | private static final String SKINDIR_PROPERTY = "tool.ui.dir.skin"; |
|
114 | ||
115 | /** |
|
116 | * Property tag for the css file that is to be |
|
117 | * used for the web application. |
|
118 | */ |
|
119 | private static final String CSS_PROPERTY = "tool.ui.css"; |
|
120 | ||
121 | /** |
|
122 | * Property tag for the css file that is to be |
|
123 | * used for the web application. |
|
124 | */ |
|
125 | private static final String RELATIVE_PROPERTY = "tool.ui.want.relative"; |
|
126 | ||
127 | /** |
|
128 | * Default skin name. This name actually represents |
|
129 | * a directory in the WEBAPP/resources/ui/skins |
|
130 | * directory. There is a file called skin.props |
|
131 | * which actually contains the name/value pairs. |
|
132 | */ |
|
133 | private static final String SKIN_PROPERTY_DEFAULT = "default"; |
|
134 | ||
135 | /** |
|
136 | * Attribute name of skinName value in User's temp hashmap. |
|
137 | */ |
|
138 | 26 | private static final String SKIN_ATTRIBUTE = |
139 | UIManager.class.getName()+ ".skin"; |
|
140 | ||
141 | /** |
|
142 | * The actual skin being used for the webapp. |
|
143 | */ |
|
144 | private String skinName; |
|
145 | ||
146 | /** |
|
147 | * The skins directory. |
|
148 | */ |
|
149 | private String skinsDirectory; |
|
150 | ||
151 | /** |
|
152 | * The file within the skin directory that actually |
|
153 | * contains the name/value pairs for the skin. |
|
154 | */ |
|
155 | private static final String SKIN_PROPS_FILE = "skin.props"; |
|
156 | ||
157 | /** |
|
158 | * The file name for the skin style sheet. |
|
159 | */ |
|
160 | private static final String DEFAULT_SKIN_CSS_FILE = "skin.css"; |
|
161 | ||
162 | /** |
|
163 | * This the resources directory relative to the |
|
164 | * webapp context. Used for constructing correct |
|
165 | * URIs for retrieving images in image(). |
|
166 | */ |
|
167 | private String resourcesDirectory; |
|
168 | private String imagesDirectory; |
|
169 | private String cssFile; |
|
170 | ||
171 | 26 | private boolean wantRelative = false; |
172 | ||
173 | /** |
|
174 | * Properties to hold the name/value pairs |
|
175 | * for the skin. |
|
176 | */ |
|
177 | private Properties skinProperties; |
|
178 | ||
179 | /** |
|
180 | * Initialize the UIManager object. |
|
181 | * |
|
182 | * @param data This is null, RunData or User depending upon specified tool scope. |
|
183 | */ |
|
184 | public void init(Object data) |
|
185 | { |
|
186 | /** |
|
187 | * Store the resources directory for use in image(). |
|
188 | */ |
|
189 | 26 | Configuration cfg = Turbine.getConfiguration(); |
190 | ||
191 | 26 | resourcesDirectory = stripSlashes(TurbinePull.getResourcesDirectory()); |
192 | ||
193 | 26 | if (data == null) |
194 | { |
|
195 | 26 | log.debug("UI Manager scope is global"); |
196 | 26 | setSkin(); |
197 | } |
|
198 | 0 | else if (data instanceof RunData) |
199 | { |
|
200 | 0 | log.debug("UI Manager scope is request"); |
201 | 0 | setSkin((RunData) data); |
202 | } |
|
203 | 0 | else if (data instanceof User) |
204 | { |
|
205 | 0 | log.debug("UI Manager scope is session"); |
206 | 0 | setSkin((User) data); |
207 | } |
|
208 | ||
209 | 26 | skinsDirectory = stripSlashes(cfg.getString(SKINDIR_PROPERTY, SKINS_DIRECTORY)); |
210 | ||
211 | 26 | imagesDirectory = stripSlashes(cfg.getString(IMAGEDIR_PROPERTY, IMAGES_DIRECTORY)); |
212 | ||
213 | 26 | cssFile = cfg.getString(CSS_PROPERTY, DEFAULT_SKIN_CSS_FILE); |
214 | ||
215 | 26 | wantRelative = cfg.getBoolean(RELATIVE_PROPERTY, false); |
216 | ||
217 | 26 | loadSkin(); |
218 | 26 | } |
219 | ||
220 | private String stripSlashes(final String path) |
|
221 | { |
|
222 | 92 | if (StringUtils.isEmpty(path)) |
223 | { |
|
224 | 2 | return ""; |
225 | } |
|
226 | ||
227 | 90 | String ret = path; |
228 | 90 | int len = ret.length() - 1; |
229 | ||
230 | 90 | if (ret.charAt(len) == '/') |
231 | { |
|
232 | 82 | ret = ret.substring(0, len); |
233 | } |
|
234 | ||
235 | 90 | if (len > 0 && ret.charAt(0) == '/') |
236 | { |
|
237 | 82 | ret = ret.substring(1); |
238 | } |
|
239 | ||
240 | 90 | return ret; |
241 | } |
|
242 | ||
243 | /** |
|
244 | * This lets the tool know that it should be |
|
245 | * refreshed. The tool can perform whatever actions |
|
246 | * are necessary to refresh itself. This is necessary |
|
247 | * for sane development where you probably want the |
|
248 | * tools to refresh themselves on every request. |
|
249 | */ |
|
250 | public void refresh() |
|
251 | { |
|
252 | 8 | log.debug("Refreshing UI manager"); |
253 | ||
254 | 8 | loadSkin(); |
255 | 8 | } |
256 | ||
257 | /** |
|
258 | * Retrieve a property from the properties held |
|
259 | * within the properties file for this skin. |
|
260 | */ |
|
261 | public String get(String key) |
|
262 | { |
|
263 | 0 | return skinProperties.getProperty(key); |
264 | } |
|
265 | ||
266 | /** |
|
267 | * Retrieve the skin name. |
|
268 | */ |
|
269 | public String getSkin() |
|
270 | { |
|
271 | 48 | return skinName; |
272 | } |
|
273 | ||
274 | /** |
|
275 | * Retrieve the URL for an image that is part |
|
276 | * of a skin. The images are stored in the |
|
277 | * WEBAPP/resources/ui/skins/<SKIN>/images |
|
278 | * directory. |
|
279 | * |
|
280 | * Use this if for some reason your server name, |
|
281 | * server scheme, or server port change on a |
|
282 | * per request basis. I'm not sure if this |
|
283 | * would happend in a load balanced situation. |
|
284 | * I think in most cases the image(String image) |
|
285 | * method would probably be enough, but I'm not |
|
286 | * absolutely positive. |
|
287 | */ |
|
288 | public String image(String imageId, RunData data) |
|
289 | { |
|
290 | 0 | DataURI du = new DataURI(data); |
291 | ||
292 | 0 | StringBuffer sb = new StringBuffer(); |
293 | ||
294 | 0 | sb.append(resourcesDirectory). |
295 | append('/'). |
|
296 | append(skinsDirectory). |
|
297 | append('/'). |
|
298 | append(getSkin()). |
|
299 | append('/'). |
|
300 | append(imagesDirectory). |
|
301 | append('/'). |
|
302 | append(stripSlashes(imageId)); |
|
303 | ||
304 | 0 | du.setScriptName(sb.toString()); |
305 | ||
306 | 0 | return wantRelative ? du.getRelativeLink() : du.getAbsoluteLink(); |
307 | } |
|
308 | ||
309 | /** |
|
310 | * Retrieve the URL for an image that is part |
|
311 | * of a skin. The images are stored in the |
|
312 | * WEBAPP/resources/ui/skins/<SKIN>/images |
|
313 | * directory. |
|
314 | */ |
|
315 | public String image(String imageId) |
|
316 | { |
|
317 | 12 | ServerData sd = Turbine.getDefaultServerData(); |
318 | 12 | DataURI du = new DataURI(sd); |
319 | ||
320 | 12 | StringBuffer sb = new StringBuffer(); |
321 | ||
322 | 12 | sb.append(resourcesDirectory). |
323 | append('/'). |
|
324 | append(skinsDirectory). |
|
325 | append('/'). |
|
326 | append(getSkin()). |
|
327 | append('/'). |
|
328 | append(imagesDirectory). |
|
329 | append('/'). |
|
330 | append(stripSlashes(imageId)); |
|
331 | ||
332 | 12 | du.setScriptName(sb.toString()); |
333 | 12 | return wantRelative ? du.getRelativeLink() : du.getAbsoluteLink(); |
334 | } |
|
335 | ||
336 | /** |
|
337 | * Retrieve the URL for the style sheet that is part |
|
338 | * of a skin. The style is stored in the |
|
339 | * WEBAPP/resources/ui/skins/<SKIN> directory with the |
|
340 | * filename skin.css |
|
341 | * |
|
342 | * Use this if for some reason your server name, |
|
343 | * server scheme, or server port change on a |
|
344 | * per request basis. I'm not sure if this |
|
345 | * would happend in a load balanced situation. |
|
346 | * I think in most cases the style() |
|
347 | * method would probably be enough, but I'm not |
|
348 | * absolutely positive. |
|
349 | */ |
|
350 | public String getStylecss(RunData data) |
|
351 | { |
|
352 | 0 | return getScript(cssFile, data); |
353 | } |
|
354 | ||
355 | /** |
|
356 | * Retrieve the URL for the style sheet that is part |
|
357 | * of a skin. The style is stored in the |
|
358 | * WEBAPP/resources/ui/skins/<SKIN> directory with the |
|
359 | * filename skin.css |
|
360 | */ |
|
361 | public String getStylecss() |
|
362 | { |
|
363 | 2 | return getScript(cssFile); |
364 | } |
|
365 | ||
366 | /** |
|
367 | * Retrieve the URL for a given script that is part |
|
368 | * of a skin. The script is stored in the |
|
369 | * WEBAPP/resources/ui/skins/<SKIN> directory |
|
370 | */ |
|
371 | public String getScript(String filename, RunData data) |
|
372 | { |
|
373 | 0 | DataURI du = new DataURI(data); |
374 | ||
375 | 0 | StringBuffer sb = new StringBuffer(); |
376 | ||
377 | 0 | sb.append(resourcesDirectory). |
378 | append('/'). |
|
379 | append(skinsDirectory). |
|
380 | append('/'). |
|
381 | append(getSkin()). |
|
382 | append('/'). |
|
383 | append(stripSlashes(filename)); |
|
384 | ||
385 | 0 | du.setScriptName(sb.toString()); |
386 | 0 | return wantRelative ? du.getRelativeLink() : du.getAbsoluteLink(); |
387 | } |
|
388 | ||
389 | /** |
|
390 | * Retrieve the URL for a given script that is part |
|
391 | * of a skin. The script is stored in the |
|
392 | * WEBAPP/resources/ui/skins/<SKIN> directory |
|
393 | */ |
|
394 | public String getScript(String filename) |
|
395 | { |
|
396 | 2 | ServerData sd = Turbine.getDefaultServerData(); |
397 | 2 | DataURI du = new DataURI(sd); |
398 | ||
399 | 2 | StringBuffer sb = new StringBuffer(); |
400 | ||
401 | 2 | sb.append(resourcesDirectory). |
402 | append('/'). |
|
403 | append(skinsDirectory). |
|
404 | append('/'). |
|
405 | append(getSkin()). |
|
406 | append('/'). |
|
407 | append(stripSlashes(filename)); |
|
408 | ||
409 | 2 | du.setScriptName(sb.toString()); |
410 | 2 | return wantRelative ? du.getRelativeLink() : du.getAbsoluteLink(); |
411 | } |
|
412 | ||
413 | /** |
|
414 | * Load the specified skin. In development mode |
|
415 | * this may occur frequently as the skin properties |
|
416 | * are being changed. |
|
417 | */ |
|
418 | private void loadSkin() |
|
419 | { |
|
420 | 34 | skinProperties = new Properties(); |
421 | ||
422 | try |
|
423 | { |
|
424 | 34 | StringBuffer sb = new StringBuffer(); |
425 | ||
426 | 34 | sb.append(resourcesDirectory). |
427 | append('/'). |
|
428 | append(skinsDirectory). |
|
429 | append('/'). |
|
430 | append(getSkin()). |
|
431 | append('/'). |
|
432 | append(SKIN_PROPS_FILE); |
|
433 | ||
434 | 34 | InputStream is = TurbineServlet.getResourceAsStream(sb.toString()); |
435 | ||
436 | 0 | skinProperties.load(is); |
437 | } |
|
438 | 17 | catch (Exception e) |
439 | { |
|
440 | 34 | log.error("Cannot load skin: " + skinName); |
441 | 0 | } |
442 | 34 | } |
443 | ||
444 | /** |
|
445 | * Set the skin name to the skin from the TR.props |
|
446 | * file. If the property is not present use the |
|
447 | * default skin. |
|
448 | */ |
|
449 | public void setSkin() |
|
450 | { |
|
451 | 26 | this.skinName = Turbine.getConfiguration() |
452 | .getString(SKIN_PROPERTY, |
|
453 | SKIN_PROPERTY_DEFAULT); |
|
454 | 26 | } |
455 | ||
456 | /** |
|
457 | * Set the skin name to the specified skin. |
|
458 | * |
|
459 | * @param skinName the skin name to use. |
|
460 | */ |
|
461 | public void setSkin(String skinName) |
|
462 | { |
|
463 | 0 | this.skinName = skinName; |
464 | 0 | } |
465 | ||
466 | /** |
|
467 | * Set the skin name when the tool is configured to be |
|
468 | * loaded on a per-request basis. By default it calls getSkin |
|
469 | * to return the skin specified in TR.properties. Developers can |
|
470 | * write a subclass of UIManager that overrides this method to |
|
471 | * determine the skin to use based on information held in the request. |
|
472 | * |
|
473 | * @param data a RunData instance |
|
474 | */ |
|
475 | protected void setSkin(RunData data) |
|
476 | { |
|
477 | 0 | setSkin(); |
478 | 0 | } |
479 | ||
480 | /** |
|
481 | * Set the skin name when the tool is configured to be |
|
482 | * loaded on a per-session basis. It the user's temp hashmap contains |
|
483 | * a value in the attribute specified by the String constant SKIN_ATTRIBUTE |
|
484 | * then that is returned. Otherwise it calls getSkin to return the skin |
|
485 | * specified in TR.properties. |
|
486 | * |
|
487 | * @param user a User instance |
|
488 | */ |
|
489 | protected void setSkin(User user) |
|
490 | { |
|
491 | 0 | if (user.getTemp(SKIN_ATTRIBUTE) == null) |
492 | { |
|
493 | 0 | setSkin(); |
494 | } |
|
495 | else |
|
496 | { |
|
497 | 0 | setSkin((String) user.getTemp(SKIN_ATTRIBUTE)); |
498 | } |
|
499 | 0 | } |
500 | ||
501 | /** |
|
502 | * Set the skin name user's temp hashmap for the current session. |
|
503 | * |
|
504 | * @param user a User instance |
|
505 | * @param skin the skin name for the session |
|
506 | */ |
|
507 | public static void setSkin(User user, String skin) |
|
508 | { |
|
509 | 0 | user.setTemp(SKIN_ATTRIBUTE, skin); |
510 | 0 | } |
511 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |