View Javadoc

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