001: package org.apache.turbine.services.pull.util;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.io.InputStream;
023: import java.util.Properties;
024:
025: import org.apache.commons.configuration.Configuration;
026: import org.apache.commons.lang.StringUtils;
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.apache.turbine.Turbine;
030: import org.apache.turbine.om.security.User;
031: import org.apache.turbine.services.pull.ApplicationTool;
032: import org.apache.turbine.services.pull.TurbinePull;
033: import org.apache.turbine.services.servlet.TurbineServlet;
034: import org.apache.turbine.util.RunData;
035: import org.apache.turbine.util.ServerData;
036: import org.apache.turbine.util.uri.DataURI;
037:
038: /**
039: * UIManager.java
040: * <br>
041: * Manages all UI elements for a Turbine Application. Any
042: * UI element can be accessed in any template using the
043: * $ui handle (assuming you use the default PullService
044: * configuration). So, for example, you could access
045: * the background colour for your pages by using
046: * $ui.bgcolor
047: * <p>
048: * <h3>Questions:</h3>
049: * What is the best way to allow an application
050: * to be skinned. And how to allow the flexible
051: * altering of a particular UI element in certain
052: * parts of the template hierarchy. For example
053: * on one section of your site you might like
054: * a certain bgcolor, on another part of your
055: * site you might want another. How can be let
056: * the designer specify these properties and
057: * still use the single $app.ui.bgcolor in
058: * all the templates.
059: * <p>
060: * It would also be very cool to use some form
061: * of inheritence for UI elements. Say a $ui.bgcolor
062: * is used in a template where the bgcolor is not
063: * set for that part of hierarch, it would be cool
064: * if it could find the setting for the bgcolor
065: * in the parent directory. So you could override
066: * a UI element where you wanted and the system
067: * would fall back to the parent when necessary.
068: * <p>
069: * How to specify skins, how to deal with images,
070: * how could this be handled with a web app.
071: * <p>
072: *
073: * This is an application pull tool for the template system. You should <b>not</b>
074: * use it in a normal application!
075: *
076: *
077: * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
078: * @author <a href="mailto:james_coltman@majorband.co.uk">James Coltman</a>
079: * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
080: * @author <a href="thomas.vandahl@tewisoft.de">Thomas Vandahl</a>
081: * @deprecated Use UITool instead.
082: * @version $Id: UIManager.java 535070 2007-05-04 03:23:22Z seade $
083: */
084: public class UIManager implements ApplicationTool {
085: /** Logging */
086: private static Log log = LogFactory.getLog(UIManager.class);
087:
088: /**
089: * The location of the skins within the application
090: * resources directory.
091: */
092: private static final String SKINS_DIRECTORY = "/ui/skins";
093:
094: /**
095: * The name of the directory where images are
096: * stored for this skin.
097: */
098: private static final String IMAGES_DIRECTORY = "/images";
099:
100: /**
101: * Property tag for the default skin that is to be
102: * used for the web application.
103: */
104: private static final String SKIN_PROPERTY = "tool.ui.skin";
105:
106: /**
107: * Property tag for the image directory inside the skin that is to be
108: * used for the web application.
109: */
110: private static final String IMAGEDIR_PROPERTY = "tool.ui.dir.image";
111:
112: /**
113: * Property tag for the skin directory that is to be
114: * used for the web application.
115: */
116: private static final String SKINDIR_PROPERTY = "tool.ui.dir.skin";
117:
118: /**
119: * Property tag for the css file that is to be
120: * used for the web application.
121: */
122: private static final String CSS_PROPERTY = "tool.ui.css";
123:
124: /**
125: * Property tag for the css file that is to be
126: * used for the web application.
127: */
128: private static final String RELATIVE_PROPERTY = "tool.ui.want.relative";
129:
130: /**
131: * Default skin name. This name actually represents
132: * a directory in the WEBAPP/resources/ui/skins
133: * directory. There is a file called skin.props
134: * which actually contains the name/value pairs.
135: */
136: private static final String SKIN_PROPERTY_DEFAULT = "default";
137:
138: /**
139: * Attribute name of skinName value in User's temp hashmap.
140: */
141: private static final String SKIN_ATTRIBUTE = UIManager.class
142: .getName()
143: + ".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: * Store the resources directory for use in image().
192: */
193: Configuration cfg = Turbine.getConfiguration();
194:
195: resourcesDirectory = stripSlashes(TurbinePull
196: .getResourcesDirectory());
197:
198: if (data == null) {
199: log.debug("UI Manager scope is global");
200: setSkin();
201: } else if (data instanceof RunData) {
202: log.debug("UI Manager scope is request");
203: setSkin((RunData) data);
204: } else if (data instanceof User) {
205: log.debug("UI Manager scope is session");
206: setSkin((User) data);
207: }
208:
209: skinsDirectory = stripSlashes(cfg.getString(SKINDIR_PROPERTY,
210: SKINS_DIRECTORY));
211:
212: imagesDirectory = stripSlashes(cfg.getString(IMAGEDIR_PROPERTY,
213: IMAGES_DIRECTORY));
214:
215: cssFile = cfg.getString(CSS_PROPERTY, DEFAULT_SKIN_CSS_FILE);
216:
217: wantRelative = cfg.getBoolean(RELATIVE_PROPERTY, false);
218:
219: loadSkin();
220: }
221:
222: private String stripSlashes(final String path) {
223: if (StringUtils.isEmpty(path)) {
224: return "";
225: }
226:
227: String ret = path;
228: int len = ret.length() - 1;
229:
230: if (ret.charAt(len) == '/') {
231: ret = ret.substring(0, len);
232: }
233:
234: if (len > 0 && ret.charAt(0) == '/') {
235: ret = ret.substring(1);
236: }
237:
238: return ret;
239: }
240:
241: /**
242: * This lets the tool know that it should be
243: * refreshed. The tool can perform whatever actions
244: * are necessary to refresh itself. This is necessary
245: * for sane development where you probably want the
246: * tools to refresh themselves on every request.
247: *
248: * @deprecated Use UITool.refresh() instead.
249: */
250: public void refresh() {
251: log.debug("Refreshing UI manager");
252:
253: loadSkin();
254: }
255:
256: /**
257: * Retrieve a property from the properties held
258: * within the properties file for this skin.
259: *
260: * @deprecated Use UITool.get(String key) instead.
261: */
262: public String get(String key) {
263: return skinProperties.getProperty(key);
264: }
265:
266: /**
267: * Retrieve the skin name.
268: *
269: * @deprecated Use UITool.getSkin() instead.
270: */
271: public String getSkin() {
272: return skinName;
273: }
274:
275: /**
276: * Retrieve the URL for an image that is part
277: * of a skin. The images are stored in the
278: * WEBAPP/resources/ui/skins/<SKIN>/images
279: * directory.
280: *
281: * Use this if for some reason your server name,
282: * server scheme, or server port change on a
283: * per request basis. I'm not sure if this
284: * would happen in a load balanced situation.
285: * I think in most cases the image(String image)
286: * method would probably be enough, but I'm not
287: * absolutely positive.
288: *
289: * @deprecated Use UITool.image(String imageId, RunData data) instead.
290: */
291: public String image(String imageId, RunData data) {
292: DataURI du = new DataURI(data);
293:
294: StringBuffer sb = new StringBuffer();
295:
296: sb.append(resourcesDirectory).append('/')
297: .append(skinsDirectory).append('/').append(getSkin())
298: .append('/').append(imagesDirectory).append('/')
299: .append(stripSlashes(imageId));
300:
301: du.setScriptName(sb.toString());
302:
303: return wantRelative ? du.getRelativeLink() : du
304: .getAbsoluteLink();
305: }
306:
307: /**
308: * Retrieve the URL for an image that is part
309: * of a skin. The images are stored in the
310: * WEBAPP/resources/ui/skins/<SKIN>/images
311: * directory.
312: *
313: * @deprecated Use UITool.image(String imageId) instead.
314: */
315: public String image(String imageId) {
316: ServerData sd = Turbine.getDefaultServerData();
317: DataURI du = new DataURI(sd);
318:
319: StringBuffer sb = new StringBuffer();
320:
321: sb.append(resourcesDirectory).append('/')
322: .append(skinsDirectory).append('/').append(getSkin())
323: .append('/').append(imagesDirectory).append('/')
324: .append(stripSlashes(imageId));
325:
326: du.setScriptName(sb.toString());
327: return wantRelative ? du.getRelativeLink() : du
328: .getAbsoluteLink();
329: }
330:
331: /**
332: * Retrieve the URL for the style sheet that is part
333: * of a skin. The style is stored in the
334: * WEBAPP/resources/ui/skins/<SKIN> directory with the
335: * filename skin.css
336: *
337: * Use this if for some reason your server name,
338: * server scheme, or server port change on a
339: * per request basis. I'm not sure if this
340: * would happend in a load balanced situation.
341: * I think in most cases the style()
342: * method would probably be enough, but I'm not
343: * absolutely positive.
344: *
345: * @deprecated Use UITool.getStylecss(RunData data) instead.
346: */
347: public String getStylecss(RunData data) {
348: return getScript(cssFile, data);
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/<SKIN> directory with the
355: * filename skin.css
356: *
357: * @deprecated Use UITool.getStylecss() instead.
358: */
359: public String getStylecss() {
360: return getScript(cssFile);
361: }
362:
363: /**
364: * Retrieve the URL for a given script that is part
365: * of a skin. The script is stored in the
366: * WEBAPP/resources/ui/skins/<SKIN> directory
367: *
368: * @deprecated Use UITool.getScript(String filename, RunData data) instead.
369: */
370: public String getScript(String filename, RunData data) {
371: DataURI du = new DataURI(data);
372:
373: StringBuffer sb = new StringBuffer();
374:
375: sb.append(resourcesDirectory).append('/')
376: .append(skinsDirectory).append('/').append(getSkin())
377: .append('/').append(stripSlashes(filename));
378:
379: du.setScriptName(sb.toString());
380: return wantRelative ? du.getRelativeLink() : du
381: .getAbsoluteLink();
382: }
383:
384: /**
385: * Retrieve the URL for a given script that is part
386: * of a skin. The script is stored in the
387: * WEBAPP/resources/ui/skins/<SKIN> directory
388: *
389: * @deprecated Use UITool.getScript(String filename) instead.
390: */
391: public String getScript(String filename) {
392: ServerData sd = Turbine.getDefaultServerData();
393: DataURI du = new DataURI(sd);
394:
395: StringBuffer sb = new StringBuffer();
396:
397: sb.append(resourcesDirectory).append('/')
398: .append(skinsDirectory).append('/').append(getSkin())
399: .append('/').append(stripSlashes(filename));
400:
401: du.setScriptName(sb.toString());
402: return wantRelative ? du.getRelativeLink() : du
403: .getAbsoluteLink();
404: }
405:
406: /**
407: * Load the specified skin. In development mode
408: * this may occur frequently as the skin properties
409: * are being changed.
410: */
411: private void loadSkin() {
412: skinProperties = new Properties();
413:
414: try {
415: StringBuffer sb = new StringBuffer();
416:
417: sb.append(resourcesDirectory).append('/').append(
418: skinsDirectory).append('/').append(getSkin())
419: .append('/').append(SKIN_PROPS_FILE);
420:
421: InputStream is = TurbineServlet.getResourceAsStream(sb
422: .toString());
423:
424: skinProperties.load(is);
425: } catch (Exception e) {
426: log.error("Cannot load skin: " + skinName);
427: }
428: }
429:
430: /**
431: * Set the skin name to the skin from the TR.props
432: * file. If the property is not present use the
433: * default skin.
434: *
435: * @deprecated Use UITool.setSkin() instead.
436: */
437: public void setSkin() {
438: this .skinName = Turbine.getConfiguration().getString(
439: SKIN_PROPERTY, SKIN_PROPERTY_DEFAULT);
440: }
441:
442: /**
443: * Set the skin name to the specified skin.
444: *
445: * @param skinName the skin name to use.
446: * @deprecated Use UITool.setSkin(String skinName) instead.
447: */
448: public void setSkin(String skinName) {
449: this .skinName = skinName;
450: }
451:
452: /**
453: * Set the skin name when the tool is configured to be
454: * loaded on a per-request basis. By default it calls getSkin
455: * to return the skin specified in TR.properties. Developers can
456: * write a subclass of UIManager that overrides this method to
457: * determine the skin to use based on information held in the request.
458: *
459: * @param data a RunData instance
460: * @deprecated Use UITool.setSkin(RunData data) instead.
461: */
462: protected void setSkin(RunData data) {
463: setSkin();
464: }
465:
466: /**
467: * Set the skin name when the tool is configured to be
468: * loaded on a per-session basis. It the user's temp hashmap contains
469: * a value in the attribute specified by the String constant SKIN_ATTRIBUTE
470: * then that is returned. Otherwise it calls getSkin to return the skin
471: * specified in TR.properties.
472: *
473: * @param user a User instance
474: * @deprecated Use UITool.setSkin(User user) instead.
475: */
476: protected void setSkin(User user) {
477: if (user.getTemp(SKIN_ATTRIBUTE) == null) {
478: setSkin();
479: } else {
480: setSkin((String) user.getTemp(SKIN_ATTRIBUTE));
481: }
482: }
483:
484: /**
485: * Set the skin name user's temp hashmap for the current session.
486: *
487: * @param user a User instance
488: * @param skin the skin name for the session
489: * @deprecated Use UITool.setSkin(User user, String skin) instead.
490: */
491: public static void setSkin(User user, String skin) {
492: user.setTemp(SKIN_ATTRIBUTE, skin);
493: }
494: }
|