You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by se...@apache.org on 2007/05/04 05:23:24 UTC

svn commit: r535070 - in /jakarta/turbine/core/branches/TURBINE_2_3_BRANCH: conf/ conf/test/ src/java/org/apache/turbine/services/pull/tools/ src/java/org/apache/turbine/services/pull/util/ src/java/org/apache/turbine/services/ui/ src/test/org/apache/t...

Author: seade
Date: Thu May  3 20:23:22 2007
New Revision: 535070

URL: http://svn.apache.org/viewvc?view=rev&rev=535070
Log:
Add UI Service with accompanying UITool that replaces UIManager.

Added:
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/pull/tools/UITool.java
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/TurbineUI.java
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/TurbineUIService.java
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/UIService.java
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/package.html
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/tools/
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/tools/UIToolTest.java
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/services/ui-service.xml
Modified:
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/TurbineResources.properties
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/test/TurbineResources.properties
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/pull/util/UIManager.java
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/util/UIManagerTest.java
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/changes.xml
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/navigation.xml
    jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/services/index.xml

Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/TurbineResources.properties
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/TurbineResources.properties?view=diff&rev=535070&r1=535069&r2=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/TurbineResources.properties (original)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/TurbineResources.properties Thu May  3 20:23:22 2007
@@ -342,6 +342,7 @@
 services.PullService.classname=org.apache.turbine.services.pull.TurbinePullService
 # services.IntakeService.classname=org.apache.turbine.services.intake.TurbineIntakeService
 services.TemplateService.classname=org.apache.turbine.services.template.TurbineTemplateService
+services.UIService.classname = org.apache.turbine.services.ui.TurbineUIService
 services.XSLTService.classname=org.apache.turbine.services.xslt.TurbineXSLTService
 # services.SessionService.classname=org.apache.turbine.services.session.TurbineSessionService
 
@@ -454,7 +455,7 @@
 #
 # For example:
 #
-# tool.global.ui    = org.apache.turbine.util.pull.UIManager
+# tool.global.ui    = org.apache.turbine.util.pull.tools.UITool
 # tool.global.mm    = org.apache.turbine.util.pull.MessageManager
 # tool.request.link = org.apache.turbine.services.pull.tools.TemplateLink
 # tool.request.page = org.apache.turbine.util.template.HtmlPageAttributes
@@ -466,7 +467,7 @@
 # configures the value of "skin" for the "ui" tool.
 #
 # Tools are accessible in all templates by the <id> given
-# to the tool. So for the above listings the UIManager would
+# to the tool. So for the above listings the UITool would
 # be available as $ui, the MessageManager as $mm, the TemplateLink
 # as $link and the HtmlPageAttributes as $page.
 #
@@ -521,7 +522,7 @@
 # properties files that are located in the WEBAPP/resources/ directory
 # hierarchy.
 
-tool.global.ui=org.apache.turbine.services.pull.util.UIManager
+tool.global.ui=org.apache.turbine.services.pull.tools.UITool
 
 # Path to the UI resources, relative to the resources directory defined above
 # tool.ui.dir.skin=/ui/skins
@@ -545,7 +546,7 @@
 #
 # The content tool can put its URIs through the Servlet container,
 # which might attach things like the jsessionid even to URIs that
-# are not servered by the container.
+# are not served by the container.
 #
 # The default behaviour was not to put these through the container.
 #

Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/test/TurbineResources.properties
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/test/TurbineResources.properties?view=diff&rev=535070&r1=535069&r2=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/test/TurbineResources.properties (original)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/conf/test/TurbineResources.properties Thu May  3 20:23:22 2007
@@ -288,6 +288,7 @@
 services.PullService.classname=org.apache.turbine.services.pull.TurbinePullService
 # services.IntakeService.classname=org.apache.turbine.services.intake.TurbineIntakeService
 services.TemplateService.classname=org.apache.turbine.services.template.TurbineTemplateService
+services.UIService.classname = org.apache.turbine.services.ui.TurbineUIService
 services.VelocityService.classname=org.apache.turbine.services.velocity.TurbineVelocityService
 services.UploadService.classname=org.apache.turbine.services.upload.TurbineUploadService
 services.SecurityService.classname=org.apache.turbine.services.security.torque.TorqueSecurityService
@@ -383,7 +384,7 @@
 #
 # For example:
 #
-# tool.global.ui    = org.apache.turbine.util.pull.UIManager
+# tool.global.ui    = org.apache.turbine.util.pull.tools.UITool
 # tool.global.mm    = org.apache.turbine.util.pull.MessageManager
 # tool.request.link = org.apache.turbine.services.pull.tools.TemplateLink
 # tool.request.page = org.apache.turbine.util.template.HtmlPageAttributes
@@ -395,7 +396,7 @@
 # configures the value of "skin" for the "ui" tool.
 #
 # Tools are accessible in all templates by the <id> given
-# to the tool. So for the above listings the UIManager would
+# to the tool. So for the above listings the UITool would
 # be available as $ui, the MessageManager as $mm, the TemplateLink
 # as $link and the HtmlPageAttributes as $page.
 #
@@ -427,7 +428,10 @@
 tool.request.page=org.apache.turbine.util.template.HtmlPageAttributes
 tool.request.content=org.apache.turbine.services.pull.tools.ContentTool
 
-tool.global.ui = org.apache.turbine.services.pull.util.UIManager
+tool.global.ui = org.apache.turbine.services.pull.tools.UITool
+## The following is the old deprecated version.  It is being added as uimanager
+## so that it can still be tested.
+tool.global.uimanager = org.apache.turbine.services.pull.util.UIManager
 
 tool.ui.dir.skin = /turbine-skins/
 tool.ui.dir.image = /turbine-images/
@@ -451,7 +455,7 @@
 #
 # The content tool can put its URIs through the Servlet container,
 # which might attach things like the jsessionid even to URIs that
-# are not servered by the container.
+# are not served by the container.
 #
 # The default behaviour was not to put these through the container.
 #

Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/pull/tools/UITool.java
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/pull/tools/UITool.java?view=auto&rev=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/pull/tools/UITool.java (added)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/pull/tools/UITool.java Thu May  3 20:23:22 2007
@@ -0,0 +1,363 @@
+package org.apache.turbine.services.pull.tools;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.services.pull.ApplicationTool;
+import org.apache.turbine.services.ui.TurbineUI;
+import org.apache.turbine.util.RunData;
+import org.apache.turbine.util.ServerData;
+
+/**
+ * Manages all UI elements for a Turbine Application. Any UI element can be 
+ * accessed in any template using the $ui handle (assuming you use the default 
+ * PullService configuration). So, for example, you could access the background 
+ * color for your pages by using $ui.bgcolor
+ * <p>
+ * This implementation provides a single level of inheritance in that if a 
+ * property does not exist in a non-default skin, the value from the default 
+ * skin will be used. By only requiring values different to those stored in 
+ * the default skin to appear in the non-default skins the amount of memory
+ * consumed in cases where the UserManager instance is used at a non-global 
+ * scope will potentially be reduced due to the fact that a shared instance of 
+ * the default skin properties can be used. Note that this inheritance only
+ * applies to property values - it does not apply to any images or stylesheets
+ * that may form part of your skins.
+ * <p>
+ * This is an application pull tool for the template system. You should not  
+ * use it in a normal application!  Within Java code you should use TurbineUI.
+ * <p>
+ *
+ * This is an application pull tool for the template system. You should
+ * <strong>only</strong> use it in a normal application to set the skin
+ * attribute for a user (setSkin(User user, String skin)) and to initialize it
+ * for the user, otherwise use TurbineUI is probably the way to go.
+ *
+ * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+ * @author <a href="mailto:james_coltman@majorband.co.uk">James Coltman</a>
+ * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
+ * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
+ * @version $Id$
+ * @see UIService
+ */
+public class UITool implements ApplicationTool
+{
+    /** Logging */
+    private static Log log = LogFactory.getLog(UITool.class);
+
+    /**
+     * Attribute name of skinName value in User's temp hashmap.
+     */
+    public static final String SKIN_ATTRIBUTE = UITool.class.getName()+ ".skin";
+
+    /**
+     * The actual skin being used for the webapp.
+     */
+    private String skinName;
+
+    /**
+     * Refresh the tool.
+     */
+    public void refresh()
+    {
+        TurbineUI.refresh(getSkin());
+        log.debug("UITool refreshed for skin: " + getSkin());
+    }
+
+    /**
+     * Provide access to the list of available skin names.
+     * 
+     * @return the available skin names.
+     */
+    public String[] getSkinNames()
+    {
+        return TurbineUI.getSkinNames();
+    }
+
+    /**
+     * Get the name of the default skin name for the web application from the 
+     * TurbineResources.properties file. If the property is not present the 
+     * name of the default skin will be returned.  Note that the web application
+     * skin name may be something other than default, in which case its 
+     * properties will default to the skin with the name "default".
+     * 
+     * @return the name of the default skin for the web application.
+     */
+    public String getWebappSkinName()
+    {
+        return TurbineUI.getWebappSkinName();
+    }
+
+    /**
+     * Retrieve a skin property.  If the property is not defined in the current
+     * skin the value for the default skin will be provided.  If the current
+     * skin does not exist then the skin configured for the webapp will be used.  
+     * If the webapp skin does not exist the default skin will be used.  If the 
+     * default skin does not exist then <code>null</code> will be returned.
+     * 
+     * @param key the key to retrieve from the skin.
+     * @return the value of the property for the named skin (defaulting to the 
+     * default skin), the webapp skin, the default skin or <code>null</code>,
+     * depending on whether or not the property or skins exist.
+     */
+    public String get(String key)
+    {
+        return TurbineUI.get(getSkin(), key);
+    }
+
+    /**
+     * Retrieve the skin name.
+     */
+    public String getSkin()
+    {
+        return skinName;
+    }
+
+    /**
+     * Set the skin name to the skin from the TurbineResources.properties file. 
+     * If the property is not present use the "default" skin.
+     */
+    public void setSkin()
+    {
+        skinName = TurbineUI.getWebappSkinName();
+    }
+
+    /**
+     * Set the skin name to the specified skin.
+     *
+     * @param skinName the skin name to use.
+     */
+    public void setSkin(String skinName)
+    {
+        this.skinName = skinName;
+    }
+
+    /**
+     * Set the skin name when the tool is configured to be loaded on a 
+     * per-request basis. By default it calls getSkin to return the skin 
+     * specified in TurbineResources.properties. Developers can write a subclass 
+     * of UITool that overrides this method to determine the skin to use based 
+     * on information held in the request.
+     *
+     * @param data a RunData instance
+     */
+    protected void setSkin(RunData data)
+    {
+        setSkin();
+    }
+
+    /**
+     * Set the skin name when the tool is configured to be loaded on a 
+     * per-session basis. If the user's temp hashmap contains a value in the 
+     * attribute specified by the String constant SKIN_ATTRIBUTE then that is 
+     * returned. Otherwise it calls getSkin to return the skin specified in 
+     * TurbineResources.properties.
+     *
+     * @param user a User instance
+     */
+    protected void setSkin(User user)
+    {
+        if (user.getTemp(SKIN_ATTRIBUTE) == null)
+        {
+            setSkin();
+        }
+        else
+        {
+            setSkin((String) user.getTemp(SKIN_ATTRIBUTE));
+        }
+    }
+
+    /**
+     * Set the skin name in the user's temp hashmap for the current session.
+     *
+     * @param user a User instance
+     * @param skin the skin name for the session
+     */
+    public static void setSkin(User user, String skin)
+    {
+        user.setTemp(SKIN_ATTRIBUTE, skin);
+    }
+
+    /**
+     * Retrieve the URL for an image that is part of the skin. The images are 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the image(String image)
+     * method would probably be enough, but I'm not absolutely positive.
+     * 
+     * @param imageId the id of the image whose URL will be generated.
+     * @param data the RunDate to use as the source of the ServerData to use as 
+     * the basis for the URL.
+     */
+    public String image(String imageId, RunData data)
+    {
+        return image(imageId, data.getServerData());
+    }
+
+    /**
+     * Retrieve the URL for an image that is part of the skin. The images are 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the image(String image)
+     * method would probably be enough, but I'm not absolutely positive.
+     * 
+     * @param imageId the id of the image whose URL will be generated.
+     * @param serverData the serverData to use as the basis for the URL.
+     */
+    public String image(String imageId, ServerData serverData)
+    {
+        return TurbineUI.image(getSkin(), imageId, serverData);
+    }
+
+    /**
+     * Retrieve the URL for an image that is part of the skin. The images are 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
+     * 
+     * @param imageId the id of the image whose URL will be generated.
+     */
+    public String image(String imageId)
+    {
+        return TurbineUI.image(getSkin(), imageId);
+    }
+
+    /**
+     * Retrieve the URL for the style sheet that is part of the skin. The style 
+     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the 
+     * filename skin.css
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the style() method would 
+     * probably be enough, but I'm not absolutely positive.
+     * 
+     * @param data the RunDate to use as the source of the ServerData to use as 
+     * the basis for the URL.
+     */
+    public String getStylecss(RunData data)
+    {
+        return getStylecss(data.getServerData());
+    }
+
+    /**
+     * Retrieve the URL for the style sheet that is part of the skin. The style 
+     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the 
+     * filename skin.css
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the style() method would 
+     * probably be enough, but I'm not absolutely positive.
+     * 
+     * @param serverData the serverData to use as the basis for the URL.
+     */
+    public String getStylecss(ServerData serverData)
+    {
+        return TurbineUI.getStylecss(getSkin(), serverData);
+    }
+
+    /**
+     * Retrieve the URL for the style sheet that is part of the skin. The style 
+     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the 
+     * filename skin.css
+     */
+    public String getStylecss()
+    {
+        return TurbineUI.getStylecss(getSkin());
+    }
+
+    /**
+     * Retrieve the URL for a given script that is part of the skin. The script
+     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the image(String image)
+     * method would probably be enough, but I'm not absolutely positive.
+     * 
+     * @param filename the name of the script file whose URL will be generated.
+     * @param data the RunDate to use as the source of the ServerData to use as 
+     * the basis for the URL.
+     */
+    public String getScript(String filename, RunData data)
+    {
+        return getScript(filename, data.getServerData());
+    }
+
+    /**
+     * Retrieve the URL for a given script that is part of the skin. The script
+     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the image(String image)
+     * method would probably be enough, but I'm not absolutely positive.
+     * 
+     * @param filename the name of the script file whose URL will be generated.
+     * @param serverData the serverData to use as the basis for the URL.
+     */
+    public String getScript(String filename, ServerData serverData)
+    {
+        return TurbineUI.getScript(getSkin(), filename, serverData);
+    }
+
+    /**
+     * Retrieve the URL for a given script that is part of the skin. The script
+     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
+     *
+     * @param filename the name of the script file whose URL will be generated.
+     */
+    public String getScript(String filename)
+    {
+        return TurbineUI.getScript(getSkin(), filename);
+    }
+
+    /**
+     * Initialize the UITool object.
+     *
+     * @param data This is null, RunData or User depending upon specified tool 
+     * scope.
+     */
+    public void init(Object data)
+    {
+        if (data == null)
+        {
+            log.debug("UITool scope is global");
+            setSkin();
+        }
+        else if (data instanceof RunData)
+        {
+            log.debug("UITool scope is request");
+            setSkin((RunData) data);
+        }
+        else if (data instanceof User)
+        {
+            log.debug("UITool scope is session");
+            setSkin((User) data);
+        }
+    }
+
+}

Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/pull/util/UIManager.java
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/pull/util/UIManager.java?view=diff&rev=535070&r1=535069&r2=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/pull/util/UIManager.java (original)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/pull/util/UIManager.java Thu May  3 20:23:22 2007
@@ -78,6 +78,7 @@
  * @author <a href="mailto:james_coltman@majorband.co.uk">James Coltman</a>
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  * @author <a href="thomas.vandahl@tewisoft.de">Thomas Vandahl</a>
+ * @deprecated Use UITool instead.
  * @version $Id$
  */
 public class UIManager implements ApplicationTool
@@ -183,6 +184,7 @@
      * Initialize the UIManager object.
      *
      * @param data This is null, RunData or User depending upon specified tool scope.
+     * @deprecated Use UITool.init() instead.
      */
     public void init(Object data)
     {
@@ -249,6 +251,8 @@
      * are necessary to refresh itself. This is necessary
      * for sane development where you probably want the
      * tools to refresh themselves on every request.
+     * 
+     * @deprecated Use UITool.refresh() instead.
      */
     public void refresh()
     {
@@ -260,6 +264,8 @@
     /**
      * Retrieve a property from the properties held
      * within the properties file for this skin.
+     *
+     * @deprecated Use UITool.get(String key) instead.
      */
     public String get(String key)
     {
@@ -268,6 +274,8 @@
 
     /**
      * Retrieve the skin name.
+     *
+     * @deprecated Use UITool.getSkin() instead.
      */
     public String getSkin()
     {
@@ -283,10 +291,12 @@
      * Use this if for some reason your server name,
      * server scheme, or server port change on a
      * per request basis. I'm not sure if this
-     * would happend in a load balanced situation.
+     * would happen in a load balanced situation.
      * I think in most cases the image(String image)
      * method would probably be enough, but I'm not
      * absolutely positive.
+     *
+     * @deprecated Use UITool.image(String imageId, RunData data) instead.
      */
     public String image(String imageId, RunData data)
     {
@@ -314,6 +324,8 @@
      * of a skin. The images are stored in the
      * WEBAPP/resources/ui/skins/&lt;SKIN&gt;/images
      * directory.
+     *
+     * @deprecated Use UITool.image(String imageId) instead.
      */
     public String image(String imageId)
     {
@@ -349,6 +361,8 @@
      * I think in most cases the style()
      * method would probably be enough, but I'm not
      * absolutely positive.
+     *
+     * @deprecated Use UITool.getStylecss(RunData data) instead.
      */
     public String getStylecss(RunData data)
     {
@@ -360,6 +374,8 @@
      * of a skin. The style is stored in the
      * WEBAPP/resources/ui/skins/&lt;SKIN&gt; directory with the
      * filename skin.css
+     *
+     * @deprecated Use UITool.getStylecss() instead.
      */
     public String getStylecss()
     {
@@ -370,6 +386,8 @@
      * Retrieve the URL for a given script that is part
      * of a skin. The script is stored in the
      * WEBAPP/resources/ui/skins/<SKIN> directory
+     *
+     * @deprecated Use UITool.getScript(String filename, RunData data) instead.
      */
     public String getScript(String filename, RunData data)
     {
@@ -393,6 +411,8 @@
      * Retrieve the URL for a given script that is part
      * of a skin. The script is stored in the
      * WEBAPP/resources/ui/skins/<SKIN> directory
+     *
+     * @deprecated Use UITool.getScript(String filename) instead.
      */
     public String getScript(String filename)
     {
@@ -448,6 +468,8 @@
      * Set the skin name to the skin from the TR.props
      * file. If the property is not present use the
      * default skin.
+     *
+     * @deprecated Use UITool.setSkin() instead.
      */
     public void setSkin()
     {
@@ -460,6 +482,7 @@
      * Set the skin name to the specified skin.
      *
      * @param skinName the skin name to use.
+     * @deprecated Use UITool.setSkin(String skinName) instead.
      */
     public void setSkin(String skinName)
     {
@@ -474,6 +497,7 @@
      * determine the skin to use based on information held in the request.
      *
      * @param data a RunData instance
+     * @deprecated Use UITool.setSkin(RunData data) instead.
      */
     protected void setSkin(RunData data)
     {
@@ -488,6 +512,7 @@
      * specified in TR.properties.
      *
      * @param user a User instance
+     * @deprecated Use UITool.setSkin(User user) instead.
      */
     protected void setSkin(User user)
     {
@@ -506,6 +531,7 @@
      *
      * @param user a User instance
      * @param skin the skin name for the session
+     * @deprecated Use UITool.setSkin(User user, String skin) instead.
      */
     public static void setSkin(User user, String skin)
     {

Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/TurbineUI.java
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/TurbineUI.java?view=auto&rev=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/TurbineUI.java (added)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/TurbineUI.java Thu May  3 20:23:22 2007
@@ -0,0 +1,225 @@
+package org.apache.turbine.services.ui;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.turbine.services.TurbineServices;
+import org.apache.turbine.util.ServerData;
+
+/** 
+ * This is a convenience class provided to allow access to the UIService
+ * through static methods.  The UIService should ALWAYS be accessed via
+ * either this class or UITool.
+ *
+ * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
+ * @version $Id$
+ * @see UIService
+ * @see UITool
+ */
+public class TurbineUI
+{
+    /**
+     * Refresh all skins.
+     */
+    public static void refresh()
+    {
+        ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME)).refresh();
+    }
+
+    /**
+     * Refresh a particular skin.
+     * 
+     * @param skinName the name of the skin to clear.
+     */
+    public static void refresh(String skinName)
+    {
+        ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME)).refresh(skinName);
+    }
+
+    /**
+     * Provide access to the list of available skin names.
+     * 
+     * @return the available skin names.
+     */
+    public static String[] getSkinNames()
+    {
+        return ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME)).getSkinNames();
+    }
+
+    /**
+     * Get the name of the default skin name for the web application from the 
+     * TurbineResources.properties file. If the property is not present the 
+     * name of the default skin will be returned.  Note that the web application
+     * skin name may be something other than default, in which case its 
+     * properties will default to the skin with the name "default".
+     * 
+     * @return the name of the default skin for the web application.
+     */
+    public static String getWebappSkinName()
+    {
+        return ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME)).getWebappSkinName();
+    }
+
+    /**
+     * Retrieve a skin property from the named skin.  If the property is not 
+     * defined in the named skin the value for the default skin will be 
+     * provided.  If the named skin does not exist then the skin configured for 
+     * the webapp will be used.  If the webapp skin does not exist the default
+     * skin will be used.  If the default skin does not exist then 
+     * <code>null</code> will be returned.
+     * 
+     * @param skinName the name of the skin to retrieve the property from.
+     * @param key the key to retrieve from the skin.
+     * @return the value of the property for the named skin (defaulting to the 
+     * default skin), the webapp skin, the default skin or <code>null</code>,
+     * depending on whether or not the property or skins exist.
+     */
+    public static String get(String skinName, String key)
+    {
+        return ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME)).get(skinName, key);
+    }
+
+    /**
+     * Retrieve a skin property from the default skin for the webapp.  If the 
+     * property is not defined in the webapp skin the value for the default skin 
+     * will be provided.  If the webapp skin does not exist the default skin 
+     * will be used.  If the default skin does not exist then <code>null</code> 
+     * will be returned.
+     * 
+     * @param key the key to retrieve.
+     * @return the value of the property for the webapp skin (defaulting to the 
+     * default skin), the default skin or <code>null</code>, depending on 
+     * whether or not the property or skins exist.
+     */
+    public static String get(String key)
+    {
+        return ((UIService) TurbineServices.getInstance()
+            .getService(UIService.SERVICE_NAME)).get(key);
+    }
+
+    /**
+     * Retrieve the URL for an image that is part of a skin. The images are 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the image(String image)
+     * method would probably be enough, but I'm not absolutely positive.
+     * 
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param imageId the id of the image whose URL will be generated.
+     * @param data the RunData to use as the source of the ServerData to use as 
+     * the basis for the URL.
+     */
+    public static String image(String skinName, String imageId, 
+            ServerData serverData)
+    {
+        return ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME))
+                        .image(skinName, imageId, serverData);
+    }
+
+    /**
+     * Retrieve the URL for an image that is part of a skin. The images are 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
+     * 
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param imageId the id of the image whose URL will be generated.
+     */
+    public static String image(String skinName, String imageId)
+    {
+        return ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME)).image(skinName, imageId);
+    }
+
+    /**
+     * Retrieve the URL for the style sheet that is part of a skin. The style is 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the 
+     * filename skin.css
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the style() method would 
+     * probably be enough, but I'm not absolutely positive.
+     * 
+     * @param skinName the name of the skin to retrieve the style sheet from.
+     * @param data the RunData to use as the source of the ServerData to use as 
+     * the basis for the URL.
+     */
+    public static String getStylecss(String skinName, ServerData serverData)
+    {
+        return ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME))
+                        .getStylecss(skinName, serverData);
+    }
+
+    /**
+     * Retrieve the URL for the style sheet that is part of a skin. The style is 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the 
+     * filename skin.css
+     * 
+     * @param skinName the name of the skin to retrieve the style sheet from.
+     */
+    public static String getStylecss(String skinName)
+    {
+        return ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME)).getStylecss(skinName);
+    }
+
+    /**
+     * Retrieve the URL for a given script that is part of the skin. The script
+     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the image(String image)
+     * method would probably be enough, but I'm not absolutely positive.
+     * 
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param filename the name of the script file whose URL will be generated.
+     * @param data the RunData to use as the source of the ServerData to use as 
+     * the basis for the URL.
+     */
+    public static String getScript(String skinName, String filename, 
+            ServerData serverData)
+    {
+        return ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME))
+                        .getScript(skinName, filename, serverData);
+    }
+
+    /**
+     * Retrieve the URL for a given script that is part of the skin. The script
+     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
+     *
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param filename the name of the script file whose URL will be generated.
+     */
+    public static String getScript(String skinName, String filename)
+    {
+        return ((UIService) TurbineServices.getInstance()
+                .getService(UIService.SERVICE_NAME)).getScript(skinName, filename);
+    }
+
+}

Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/TurbineUIService.java
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/TurbineUIService.java?view=auto&rev=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/TurbineUIService.java (added)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/TurbineUIService.java Thu May  3 20:23:22 2007
@@ -0,0 +1,528 @@
+package org.apache.turbine.services.ui;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Properties;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.turbine.Turbine;
+import org.apache.turbine.services.InitializationException;
+import org.apache.turbine.services.TurbineBaseService;
+import org.apache.turbine.services.pull.TurbinePull;
+import org.apache.turbine.services.servlet.TurbineServlet;
+import org.apache.turbine.util.ServerData;
+import org.apache.turbine.util.uri.DataURI;
+
+/**
+ * The UI service provides for shared access to User Interface (skin) files,
+ * as well as the ability for non-default skin files to inherit properties from 
+ * a default skin.  Use TurbineUI to access skin properties from your screen 
+ * classes and action code. UITool is provided as a pull tool for accessing 
+ * skin properties from your templates. 
+ *
+ * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
+ * @author <a href="mailto:james_coltman@majorband.co.uk">James Coltman</a>
+ * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
+ * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
+ * @author <a href="thomas.vandahl@tewisoft.de">Thomas Vandahl</a>
+ * @version $Id$
+ * @see UIService
+ * @see UITool
+ */
+public class TurbineUIService
+        extends TurbineBaseService
+        implements UIService
+{
+    /**
+     * A FilenameFilter that returns only directories.
+     * TODO Replace with commons-io DirectoryFileFilter
+     */
+    private class DirectoryFileFilter implements FilenameFilter
+    {
+        public boolean accept(File dir, String fileName)
+        {
+            File file = new File(dir, fileName);
+            if (file.isDirectory())
+            {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private static Log log = LogFactory.getLog(TurbineUIService.class);
+
+    /**
+     * The location of the skins within the application resources directory.
+     */
+    private static final String SKINS_DIRECTORY = "/ui/skins";
+
+    /**
+     * The name of the directory where images are stored for this skin.
+     */
+    private static final String IMAGES_DIRECTORY = "/images";
+
+    /**
+     * Property tag for the default skin that is to be used for the web
+     * application.
+     */
+    private static final String SKIN_PROPERTY = "tool.ui.skin";
+
+    /**
+     * Property tag for the image directory inside the skin that is to be used
+     * for the web application.
+     */
+    private static final String IMAGEDIR_PROPERTY = "tool.ui.dir.image";
+
+    /**
+     * Property tag for the skin directory that is to be used for the web
+     * application.
+     */
+    private static final String SKINDIR_PROPERTY = "tool.ui.dir.skin";
+
+    /**
+     * Property tag for the css file that is to be used for the web application.
+     */
+    private static final String CSS_PROPERTY = "tool.ui.css";
+
+    /**
+     * Property tag for indicating if relative links are wanted for the web
+     * application.
+     */
+    private static final String RELATIVE_PROPERTY = "tool.ui.want.relative";
+
+    /**
+     * Default skin name. This name refers to a directory in the 
+     * WEBAPP/resources/ui/skins directory. There is a file called skin.props
+     * which contains the name/value pairs to be made available via the skin.
+     */
+    public static final String SKIN_PROPERTY_DEFAULT = "default";
+
+    /**
+     * The skins directory.
+     */
+    private String skinsDirectory;
+
+    /**
+     * The file within the skin directory that actually contains the name/value 
+     * pairs for the skin.
+     */
+    private static final String SKIN_PROPS_FILE = "skin.props";
+
+    /**
+     * The file name for the skin style sheet.
+     */
+    private static final String DEFAULT_SKIN_CSS_FILE = "skin.css";
+
+    /**
+     * This the resources directory relative to the webapp context. Used for
+     * constructing correct URIs for retrieving skin files.
+     */
+    private String resourcesDirectory;
+    private String imagesDirectory;
+    private String cssFile;
+
+    private boolean wantRelative = false;
+
+    /**
+     * The skin Properties store.
+     */
+    private HashMap skins = new HashMap();
+
+    /**
+     * Refresh the service by clearing all skins.
+     */
+    public void refresh()
+    {
+        clearSkins();
+    }
+
+    /**
+     * Refresh a particular skin by clearing it.
+     * 
+     * @param skinName the name of the skin to clear.
+     */
+    public void refresh(String skinName)
+    {
+        clearSkin(skinName);
+    }
+    
+    /**
+     * Retrieve the Properties for a specific skin.  If they are not yet loaded
+     * they will be.  If the specified skin does not exist properties for the
+     * default skin configured for the webapp will be returned and an error
+     * level message will be written to the log.  If the webapp skin does not
+     * exist the default skin will be used and id that doesn't exist an empty
+     * Properties will be returned.
+     * 
+     * @param skinName the name of the skin whose properties are to be 
+     * retrieved.
+     * @return the Properties for the named skin or the properties for the 
+     * default skin configured for the webapp if the named skin does not exist.
+     */
+    private Properties getSkinProperties(String skinName)
+    {
+        Properties skinProperties = (Properties) skins.get(skinName);
+        return null != skinProperties ? skinProperties : loadSkin(skinName); 
+    }
+
+    /**
+     * Retrieve a skin property from the named skin.  If the property is not 
+     * defined in the named skin the value for the default skin will be 
+     * provided.  If the named skin does not exist then the skin configured for 
+     * the webapp will be used.  If the webapp skin does not exist the default
+     * skin will be used.  If the default skin does not exist then 
+     * <code>null</code> will be returned.
+     * 
+     * @param skinName the name of the skin to retrieve the property from.
+     * @param key the key to retrieve from the skin.
+     * @return the value of the property for the named skin (defaulting to the 
+     * default skin), the webapp skin, the default skin or <code>null</code>,
+     * depending on whether or not the property or skins exist.
+     */
+    public String get(String skinName, String key)
+    {
+        Properties skinProperties = getSkinProperties(skinName);
+        return skinProperties.getProperty(key);
+    }
+
+    /**
+     * Retrieve a skin property from the default skin for the webapp.  If the 
+     * property is not defined in the webapp skin the value for the default skin 
+     * will be provided.  If the webapp skin does not exist the default skin 
+     * will be used.  If the default skin does not exist then <code>null</code> 
+     * will be returned.
+     * 
+     * @param key the key to retrieve.
+     * @return the value of the property for the webapp skin (defaulting to the 
+     * default skin), the default skin or <code>null</code>, depending on 
+     * whether or not the property or skins exist.
+     */
+    public String get(String key)
+    {
+        return get(getWebappSkinName(), key);
+    }
+
+    /**
+     * Provide access to the list of available skin names.
+     * 
+     * @return the available skin names.
+     */
+    public String[] getSkinNames()
+    {
+        File skinsDir = new File(skinsDirectory);
+        return skinsDir.list(new DirectoryFileFilter());
+    }
+
+    /**
+     * Clear the map of stored skins. 
+     */
+    private void clearSkins()
+    {
+        synchronized (skins)
+        {
+            skins = new HashMap();
+        }
+        log.debug("All skins were cleared.");
+    }
+    
+    /**
+     * Clear a particular skin from the map of stored skins.
+     * 
+     * @param skinName the name of the skin to clear.
+     */
+    private void clearSkin(String skinName)
+    {
+        synchronized (skins)
+        {
+            if (!skinName.equals(SKIN_PROPERTY_DEFAULT))
+            {
+                skins.remove(SKIN_PROPERTY_DEFAULT);
+            }
+            skins.remove(skinName);
+        }
+        log.debug("The skin \"" + skinName 
+                + "\" was cleared (will also clear \"default\" skin).");
+    }
+
+    /**
+     * Load the specified skin.
+     * 
+     * @param skinName the name of the skin to load.
+     * @return the Properties for the named skin if it exists, or the skin
+     * configured for the web application if it does not exist, or the default
+     * skin if that does not exist, or an empty Parameters object if even that 
+     * cannot be found.
+     */
+    private synchronized Properties loadSkin(String skinName)
+    {
+        Properties defaultSkinProperties = null;
+        
+        if (!StringUtils.equals(skinName, SKIN_PROPERTY_DEFAULT))
+        {
+            defaultSkinProperties = getSkinProperties(SKIN_PROPERTY_DEFAULT);
+        }
+
+        // The following line is okay even for default.
+        Properties skinProperties = new Properties(defaultSkinProperties);
+        
+        StringBuffer sb = new StringBuffer();
+        sb.append('/').append(resourcesDirectory);
+        sb.append('/').append(skinsDirectory);
+        sb.append('/').append(skinName);
+        sb.append('/').append(SKIN_PROPS_FILE);
+        if (log.isDebugEnabled())
+        {
+            log.debug("Loading selected skin from: " + sb.toString());
+        }
+
+        try
+        {
+            InputStream is = TurbineServlet.getResourceAsStream(sb.toString());
+
+            skinProperties.load(is);
+        }
+        catch (Exception e)
+        {
+            log.error("Cannot load skin: " + skinName + ", from: "
+                    + sb.toString(), e);
+            if (!StringUtils.equals(skinName, getWebappSkinName()) 
+                    && !StringUtils.equals(skinName, SKIN_PROPERTY_DEFAULT))
+            {
+                log.error("Attempting to return the skin configured for " 
+                        + "webapp instead of " + skinName);
+                return getSkinProperties(getWebappSkinName());
+            }
+            else if (!StringUtils.equals(skinName, SKIN_PROPERTY_DEFAULT))
+            {
+                log.error("Return the default skin instead of " + skinName);
+                return skinProperties; // Already contains the default skin.
+            }
+            else
+            {
+                log.error("No skins available - returning an empty Properties");
+                return new Properties();
+            }
+        }
+        
+        // Replace in skins HashMap
+        synchronized (skins)
+        {
+            skins.put(skinName, skinProperties);
+        }
+        
+        return skinProperties;
+    }
+
+    /**
+     * Get the name of the default skin name for the web application from the 
+     * TurbineResources.properties file. If the property is not present the 
+     * name of the default skin will be returned.  Note that the web application
+     * skin name may be something other than default, in which case its 
+     * properties will default to the skin with the name "default".
+     * 
+     * @return the name of the default skin for the web application.
+     */
+    public String getWebappSkinName()
+    {
+        return Turbine.getConfiguration()
+                .getString(SKIN_PROPERTY, SKIN_PROPERTY_DEFAULT);
+    }
+
+    /**
+     * Retrieve the URL for an image that is part of a skin. The images are 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the image(String image)
+     * method would probably be enough, but I'm not absolutely positive.
+     * 
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param imageId the id of the image whose URL will be generated.
+     * @param serverData the serverData to use as the basis for the URL.
+     */
+    public String image(String skinName, String imageId, ServerData serverData)
+    {
+        return getSkinResource(serverData, skinName, imagesDirectory, imageId);
+    }
+
+    /**
+     * Retrieve the URL for an image that is part of a skin. The images are 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
+     * 
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param imageId the id of the image whose URL will be generated.
+     */
+    public String image(String skinName, String imageId)
+    {
+        return image(skinName, imageId, Turbine.getDefaultServerData());
+    }
+
+    /**
+     * Retrieve the URL for the style sheet that is part of a skin. The style is 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the 
+     * filename skin.css
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the style() method would 
+     * probably be enough, but I'm not absolutely positive.
+     * 
+     * @param skinName the name of the skin to retrieve the style sheet from.
+     * @param serverData the serverData to use as the basis for the URL.
+     */
+    public String getStylecss(String skinName, ServerData serverData)
+    {
+        return getSkinResource(serverData, skinName, null, cssFile);
+    }
+
+    /**
+     * Retrieve the URL for the style sheet that is part of a skin. The style is 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the 
+     * filename skin.css
+     * 
+     * @param skinName the name of the skin to retrieve the style sheet from.
+     */
+    public String getStylecss(String skinName)
+    {
+        return getStylecss(skinName, Turbine.getDefaultServerData());
+    }
+
+    /**
+     * Retrieve the URL for a given script that is part of a skin. The script is
+     * stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the style() method would 
+     * probably be enough, but I'm not absolutely positive.
+     *
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param filename the name of the script file.
+     * @param serverData the serverData to use as the basis for the URL.
+     */
+    public String getScript(String skinName, String filename,
+            ServerData serverData)
+    {
+        return getSkinResource(serverData, skinName, null, filename);
+    }
+
+    /**
+     * Retrieve the URL for a given script that is part of a skin. The script is
+     * stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
+     *
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param filename the name of the script file.
+     */
+    public String getScript(String skinName, String filename)
+    {
+        return getScript(skinName, filename, Turbine.getDefaultServerData());
+    }
+
+    private String stripSlashes(final String path)
+    {
+        if (StringUtils.isEmpty(path))
+        {
+            return "";
+        }
+
+        String ret = path;
+        int len = ret.length() - 1;
+
+        if (ret.charAt(len) == '/')
+        {
+            ret = ret.substring(0, len);
+        }
+
+        if (len > 0 && ret.charAt(0) == '/')
+        {
+            ret = ret.substring(1);
+        }
+
+        return ret;
+    }
+
+    /**
+     * Construct the URL to the skin resource.
+     *
+     * @param serverData the serverData to use as the basis for the URL.
+     * @param skinName the name of the skin.
+     * @param subDir the sub-directory in which the resource resides or
+     * <code>null</code> if it is in the root directory of the skin.
+     * @param resourceName the name of the resource to be retrieved.
+     * @return the path to the resource.
+     */
+    private String getSkinResource(ServerData serverData, String skinName,
+            String subDir, String resourceName)
+    {
+        StringBuffer sb = new StringBuffer(resourcesDirectory);
+        sb.append("/").append(skinsDirectory);
+        sb.append("/").append(skinName);
+        if (subDir != null)
+        {
+            sb.append("/").append(subDir);
+        }
+        sb.append("/").append(stripSlashes(resourceName));
+
+        DataURI du = new DataURI(serverData);
+        du.setScriptName(sb.toString());
+        return wantRelative ? du.getRelativeLink() : du.getAbsoluteLink();
+    }
+
+    // ---- Service initilization ------------------------------------------
+
+    /**
+     * Initializes the service.
+     */
+    public void init() throws InitializationException
+    {
+        Configuration cfg = Turbine.getConfiguration();
+
+        // Get the resources directory that is specified in the TR.props or 
+        // default to "resources", relative to the webapp.
+        resourcesDirectory = stripSlashes(TurbinePull.getResourcesDirectory());
+
+        skinsDirectory = stripSlashes(cfg.getString(SKINDIR_PROPERTY, SKINS_DIRECTORY));
+        imagesDirectory = stripSlashes(cfg.getString(IMAGEDIR_PROPERTY, IMAGES_DIRECTORY));
+        cssFile = cfg.getString(CSS_PROPERTY, DEFAULT_SKIN_CSS_FILE);
+        wantRelative = cfg.getBoolean(RELATIVE_PROPERTY, false);
+
+        setInit(true);
+    }
+
+    /**
+     * Returns to uninitialized state.
+     */
+    public void shutdown()
+    {
+        clearSkins();
+
+        setInit(false);
+    }
+
+}

Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/UIService.java
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/UIService.java?view=auto&rev=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/UIService.java (added)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/UIService.java Thu May  3 20:23:22 2007
@@ -0,0 +1,179 @@
+package org.apache.turbine.services.ui;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.turbine.services.Service;
+import org.apache.turbine.util.ServerData;
+
+/**
+ * The UI service provides for shared access to User Interface (skin) files,
+ * as well as the ability for non-default skin files to inherit properties from 
+ * a default skin.  Use TurbineUI to access skin properties from your screen 
+ * classes and action code. UITool is provided as a pull tool for accessing 
+ * skin properties from your templates.
+ *
+ * <p>Skins are lazy loaded in that they are not loaded until first used.
+ *
+ * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
+ * @version $Id$
+ * @see UIService
+ * @see UITool
+ */
+public interface UIService extends Service
+{
+    /**
+     * The service identifier.
+     */
+    public String SERVICE_NAME = "UIService";
+    
+    /**
+     * Refresh all skins.
+     */
+    public void refresh();
+
+    /**
+     * Refresh a particular skin.
+     * 
+     * @param skinName the name of the skin to clear.
+     */
+    public void refresh(String skinName);
+
+    /**
+     * Provide access to the list of available skin names.
+     * 
+     * @return the available skin names.
+     */
+    public String[] getSkinNames();
+
+    /**
+     * Get the name of the default skin name for the web application from the 
+     * TurbineResources.properties file. If the property is not present the 
+     * name of the default skin will be returned.  Note that the web application
+     * skin name may be something other than default, in which case its 
+     * properties will default to the skin with the name "default".
+     * 
+     * @return the name of the default skin for the web application.
+     */
+    public String getWebappSkinName();
+
+    /**
+     * Retrieve a skin property from the named skin.  If the property is not 
+     * defined in the named skin the value for the default skin will be 
+     * provided.  If the named skin does not exist then the skin configured for 
+     * the webapp will be used.  If the webapp skin does not exist the default
+     * skin will be used.  If the default skin does not exist then 
+     * <code>null</code> will be returned.
+     * 
+     * @param skinName the name of the skin to retrieve the property from.
+     * @param key the key to retrieve from the skin.
+     * @return the value of the property for the named skin (defaulting to the 
+     * default skin), the webapp skin, the default skin or <code>null</code>,
+     * depending on whether or not the property or skins exist.
+     */
+    public String get(String skinName, String key);
+
+    /**
+     * Retrieve a skin property from the default skin for the webapp.  If the 
+     * property is not defined in the webapp skin the value for the default skin 
+     * will be provided.  If the webapp skin does not exist the default skin 
+     * will be used.  If the default skin does not exist then <code>null</code> 
+     * will be returned.
+     * 
+     * @param key the key to retrieve.
+     * @return the value of the property for the webapp skin (defaulting to the 
+     * default skin), the default skin or <code>null</code>, depending on 
+     * whether or not the property or skins exist.
+     */
+    public String get(String key);
+
+    /**
+     * Retrieve the URL for an image that is part of a skin. The images are 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the image(String image)
+     * method would probably be enough, but I'm not absolutely positive.
+     * 
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param imageId the id of the image whose URL will be generated.
+     * @param serverData the serverData to use as the basis for the URL.
+     */
+    public String image(String skinName, String imageId, ServerData serverData);
+
+    /**
+     * Retrieve the URL for an image that is part of a skin. The images are 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
+     * 
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param imageId the id of the image whose URL will be generated.
+     */
+    public String image(String skinName, String imageId);
+
+    /**
+     * Retrieve the URL for the style sheet that is part of a skin. The style is 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the 
+     * filename skin.css
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the style() method would 
+     * probably be enough, but I'm not absolutely positive.
+     * 
+     * @param skinName the name of the skin to retrieve the style sheet from.
+     * @param serverData the serverData to use as the basis for the URL.
+     */
+    public String getStylecss(String skinName, ServerData serverData);
+
+    /**
+     * Retrieve the URL for the style sheet that is part of a skin. The style is 
+     * stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the 
+     * filename skin.css
+     * 
+     * @param skinName the name of the skin to retrieve the style sheet from.
+     */
+    public String getStylecss(String skinName);
+
+    /**
+     * Retrieve the URL for a given script that is part of a skin. The script is
+     * stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
+     *
+     * <p>Use this if for some reason your server name, server scheme, or server 
+     * port change on a per request basis. I'm not sure if this would happen in 
+     * a load balanced situation. I think in most cases the style() method would 
+     * probably be enough, but I'm not absolutely positive.
+     *
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param filename the name of the script file.
+     * @param serverData the serverData to use as the basis for the URL.
+     */
+    public String getScript(String skinName, String filename,
+            ServerData serverData);
+
+    /**
+     * Retrieve the URL for a given script that is part of a skin. The script is
+     * stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
+     *
+     * @param skinName the name of the skin to retrieve the image from.
+     * @param filename the name of the script file.
+     */
+    public String getScript(String skinName, String filename);
+
+}

Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/package.html
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/package.html?view=auto&rev=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/package.html (added)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/java/org/apache/turbine/services/ui/package.html Thu May  3 20:23:22 2007
@@ -0,0 +1,29 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<html>
+<head>
+<!-- head part is ignored -->
+</head>
+
+<body>
+Provides skinning facilities for a Turbine web application.
+<br>
+<font size="-2">$Id$</font>
+</body>
+</html>

Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/tools/UIToolTest.java
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/tools/UIToolTest.java?view=auto&rev=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/tools/UIToolTest.java (added)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/tools/UIToolTest.java Thu May  3 20:23:22 2007
@@ -0,0 +1,106 @@
+package org.apache.turbine.services.pull.tools;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.turbine.services.pull.PullService;
+import org.apache.turbine.services.pull.TurbinePull;
+import org.apache.turbine.test.BaseTurbineTest;
+import org.apache.velocity.context.Context;
+
+
+public class UIToolTest
+        extends BaseTurbineTest
+{
+    public UIToolTest(String name)
+            throws Exception
+    {
+        super(name, "conf/test/TurbineResources.properties");
+    }
+
+    public static Test suite()
+    {
+        return new TestSuite(UIToolTest.class);
+    }
+
+    private UITool getTool()
+    {
+        PullService pullService = TurbinePull.getService();
+        assertNotNull(pullService);
+
+        Context globalContext = pullService.getGlobalContext();
+        assertNotNull(globalContext);
+
+        return (UITool) globalContext.get("ui");
+    }
+
+    public void testTool()
+    {
+        UITool ui = getTool();
+        assertNotNull(ui);
+    }
+
+    public void testCssSlashes()
+    {
+        UITool ui = getTool();
+
+        String cssUrl = ui.getStylecss();
+        assertEquals("CSS URL does not match", "http:///turbine-resources/turbine-skins/myskin/skins.css", cssUrl);
+    }
+
+    public void testImageSlashes()
+    {
+        UITool ui = getTool();
+
+        String img = "myimage.gif";
+
+        String imgUrl = ui.image(img);
+        assertEquals("CSS URL does not match", "http:///turbine-resources/turbine-skins/myskin/turbine-images/" + img, imgUrl);
+
+        String img2 = "foo/myimage.gif";
+
+        String imgUrl2 = ui.image(img2);
+        assertEquals("CSS URL does not match", "http:///turbine-resources/turbine-skins/myskin/turbine-images/" + img2, imgUrl2);
+
+        String img3 = "/foo/myimage.gif";
+
+        String imgUrl3 = ui.image(img3);
+        assertEquals("CSS URL does not match", "http:///turbine-resources/turbine-skins/myskin/turbine-images" + img3, imgUrl3);
+    }
+
+    public void testPathologicalCases()
+    {
+    	UITool ui = getTool();
+
+    	String img = "";
+        String imgUrl = ui.image(img);
+        assertEquals("Could not strip empty String", "http:///turbine-resources/turbine-skins/myskin/turbine-images/", imgUrl);
+
+    	img = "/";
+        imgUrl = ui.image(img);
+        assertEquals("Could not strip single Slash", "http:///turbine-resources/turbine-skins/myskin/turbine-images/", imgUrl);
+
+    	img = "//";
+        imgUrl = ui.image(img);
+        assertEquals("Could not strip double Slash", "http:///turbine-resources/turbine-skins/myskin/turbine-images/", imgUrl);
+    }
+}

Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/util/UIManagerTest.java
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/util/UIManagerTest.java?view=diff&rev=535070&r1=535069&r2=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/util/UIManagerTest.java (original)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/src/test/org/apache/turbine/services/pull/util/UIManagerTest.java Thu May  3 20:23:22 2007
@@ -50,7 +50,7 @@
         Context globalContext = pullService.getGlobalContext();
         assertNotNull(globalContext);
 
-        return (UIManager) globalContext.get("ui");
+        return (UIManager) globalContext.get("uimanager");
     }
 
     public void testTool()

Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/changes.xml?view=diff&rev=535070&r1=535069&r2=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/changes.xml (original)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/changes.xml Thu May  3 20:23:22 2007
@@ -28,6 +28,10 @@
 
 <body>
   <release version="2.3.3-dev" date="in Subversion">
+    <action type="add" dev="seade">
+      Added UI Service as a replacement for the UIManager pull tool (now
+      deprecated in favor of the backwards compatible UITool).
+    </action>
     <action type="update" dev="tv">
       Deprecated the DBSecurityService and its associated classes. It has been
       replaced by the TorqueSecurityService.

Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/navigation.xml
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/navigation.xml?view=diff&rev=535070&r1=535069&r2=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/navigation.xml (original)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/navigation.xml Thu May  3 20:23:22 2007
@@ -65,6 +65,7 @@
         <item name="Template Service"    href="/services/template-service.html"/>
         <item name="Torque Security Service" href="/services/torque-security-service.html"/>
         <item name="Torque Security Service Schema" href="/services/torque-security-schema.html"/>
+        <item name="UI Service"          href="/services/ui-service.html"/>
         <item name="Unique ID Service"   href="/services/uniqueid-service.html"/>
         <item name="Upload Service"      href="/services/upload-service.html"/>
         <item name="Velocity Service"    href="/services/velocity-service.html"/>

Modified: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/services/index.xml
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/services/index.xml?view=diff&rev=535070&r1=535069&r2=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/services/index.xml (original)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/services/index.xml Thu May  3 20:23:22 2007
@@ -217,6 +217,12 @@
 </li>
 
 <li>
+<a href="ui-service.html">UI Service</a>
+<br/>
+The UI (User Interface) Service provides for application skinning.
+</li>
+
+<li>
 <a href="uniqueid-service.html">Unique ID Service</a>
 <br/>
 Allows for the creation of Context unique and pseudo random identifiers.

Added: jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/services/ui-service.xml
URL: http://svn.apache.org/viewvc/jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/services/ui-service.xml?view=auto&rev=535070
==============================================================================
--- jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/services/ui-service.xml (added)
+++ jakarta/turbine/core/branches/TURBINE_2_3_BRANCH/xdocs/services/ui-service.xml Thu May  3 20:23:22 2007
@@ -0,0 +1,217 @@
+<?xml version="1.0"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<document>
+
+ <properties>
+  <title>Turbine Services - UI Service</title>
+  <author email="seade@backstagetech.com.au">Scott Eade</author>
+ </properties>
+
+<body>
+
+<section name="UI Service">
+
+<p>
+The UI (User Interface) Service allows your Turbine application to be skinned
+using simple properties files that are located in the WEBAPP/resources/ui/skins/
+directory hierarchy.
+</p>
+
+<p>
+The service and its associated pull tool provide the following enhancements over
+the old UIManager pull tool (which has been deprecated as od Turbine 2.3.3):
+</p>
+<ul>
+<li>Skin properties are shared between all users with lazy loading.</li>
+<li>Non-default skin files inherit properties from the default skin</li>
+<li>Access to skin properties from screen and action classes is now provided for</li>
+<li>Access is provided to the list of available skins</li>
+</ul>
+
+</section>
+
+<section name="Configuration">
+
+<source><![CDATA[
+# -------------------------------------------------------------------
+#
+#  S E R V I C E S
+#
+# -------------------------------------------------------------------
+...
+services.UIService.classname = org.apache.turbine.services.ui.TurbineUIService
+...
+
+# -------------------------------------------------------------------
+#
+#  P U L L  S E R V I C E
+#
+# -------------------------------------------------------------------
+...
+## session scope allows us to pul the name of the selected skin from user.Temp
+## If you wanted the same skin to apply for all users you could use global scope.
+tool.session.ui = org.apache.turbine.services.pull.tools.UITool
+tool.ui.skin = default
+...
+]]></source>
+
+<p>
+Skin properties are defined in WEBAPP/resources/ui/skins/, the following might
+exist in a file WEBAPP/resources/ui/skins/default/skin.props:
+</p>
+
+<source><![CDATA[
+checkedImage = check.gif
+checkedImageAltText = Tick
+label_Introduction = Introduction
+l10n_label_introduction = introduction
+]]></source>
+
+<p>
+and the following might
+exist in a file WEBAPP/resources/ui/skins/custom_skin_1/skin.props:
+</p>
+
+<source><![CDATA[
+checkedImage = check-blue.gif
+checkedImageAltText = Blue tick
+label_Introduction = Summary
+l10n_label_introduction = summary
+]]></source>
+
+</section>
+
+<section name="Usage">
+
+<p>
+Retrieving a value from a skin is as simple as (where user.getSkin() returns the
+name of the currently selected skin):
+</p>
+
+<source><![CDATA[
+TurbineUI.get(user.getSkin(), "label_Introduction")
+]]></source>
+
+<p>
+or in a template (the current skin is retrieved from user.Temp):
+</p>
+
+<source><![CDATA[
+$ui.label_Introduction
+]]></source>
+
+<p>
+Images, css and javascript files are stored under the skin directory also and
+can be accessed thus:
+</p>
+
+<source><![CDATA[
+#set($imageurl = $ui.image($imageName))
+## Filename is skin.css
+#set($cssurl = $ui.getStylecss())
+#set($jsurl = $ui.getScript($filename))
+]]></source>
+
+<p>
+You can retrieve an array containing the names of the available skins thus:
+</p>
+
+<source><![CDATA[
+  String[] availableSkins = TurbineUI.getSkinNames();
+]]></source>
+
+<p>
+or in a template:
+</p>
+
+<source><![CDATA[
+  #set($availablekins = $ui.SkinNames)
+]]></source>
+
+<p>
+You can combine skinning and <a href="localization-service.html">localization</a>
+thus:
+</p>
+
+<source><![CDATA[
+## Retrieve the localized label_introduction or label_summary depending on the
+## selected skin
+$l10n.get("label_$ui.l10n_label_introduction")
+]]></source>
+
+<p>
+Please refer to the JavaDocs for the org.apache.turbine.services.ui package for
+further details.
+</p>
+
+</section>
+
+<section name="Properties">
+<p>
+You can configure the UI Service using the following properties:
+</p>
+
+<table>
+<tr>
+<th>Property</th>
+<th>Default</th>
+<th>Function</th>
+</tr>
+<tr>
+<td>tool.ui.dir.skin</td>
+<td>/ui/skins</td>
+<td>The name of the skin directory that is to be used for the web application.</td>
+</tr>
+<tr>
+<td>tool.ui.skin</td>
+<td>default</td>
+<td>The name of the default skin that is to be used for the web application.</td>
+</tr>
+<tr>
+<td>tool.ui.dir.image</td>
+<td>/images</td>
+<td>The name of the image directory inside the skin that is to be used for the
+ web application.</td>
+</tr>
+<tr>
+<td>tool.ui.css</td>
+<td>skin.css</td>
+<td>The name of the css file that is to be used for the web application.</td>
+</tr>
+
+<tr>
+<td>tool.ui.want.relative</td>
+<td>false</td>
+<td>You can configure the UI Service to return relative links for the web
+ application by setting this to <code>true</code>.</td>
+</tr>
+</table>
+
+<p>
+Note that the name of the file within the skin directory that actually contains
+the name/value pairs for the skin is fixed at <em>skin.props</em>.
+</p>
+
+</section>
+
+</body>
+</document>



---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org