    001package org.apache.turbine.services.pull.tools;
    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
    022import org.apache.commons.logging.Log;
    023import org.apache.commons.logging.LogFactory;
    024import org.apache.turbine.om.security.User;
    025import org.apache.turbine.pipeline.PipelineData;
    026import org.apache.turbine.services.pull.ApplicationTool;
    027import org.apache.turbine.services.ui.TurbineUI;
    028import org.apache.turbine.services.ui.UIService;
    029import org.apache.turbine.util.RunData;
    030import org.apache.turbine.util.ServerData;
    031
    032/**
    033 * Manages all UI elements for a Turbine Application. Any UI element can be
    034 * accessed in any template using the $ui handle (assuming you use the default
    035 * PullService configuration). So, for example, you could access the background
    036 * color for your pages by using $ui.bgcolor
    037 * <p>
    038 * This implementation provides a single level of inheritance in that if a
    039 * property does not exist in a non-default skin, the value from the default
    040 * skin will be used. By only requiring values different to those stored in
    041 * the default skin to appear in the non-default skins the amount of memory
    042 * consumed in cases where the UserManager instance is used at a non-global
    043 * scope will potentially be reduced due to the fact that a shared instance of
    044 * the default skin properties can be used. Note that this inheritance only
    045 * applies to property values - it does not apply to any images or stylesheets
    046 * that may form part of your skins.
    047 * <p>
    048 * This is an application pull tool for the template system. You should not
    049 * use it in a normal application!  Within Java code you should use TurbineUI.
    050 * <p>
    051 *
    052 * This is an application pull tool for the template system. You should
    053 * <strong>only</strong> use it in a normal application to set the skin
    054 * attribute for a user (setSkin(User user, String skin)) and to initialize it
    055 * for the user, otherwise use TurbineUI is probably the way to go.
    056 *
    057 * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
    058 * @author <a href="mailto:james_coltman@majorband.co.uk">James Coltman</a>
    059 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    060 * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
    061 * @version $Id$
    062 * @see UIService
    063 */
    064public class UITool implements ApplicationTool
    065{
    066    /** Logging */
    067    private static Log log = LogFactory.getLog(UITool.class);
    068
    069    /**
    070     * Attribute name of skinName value in User's temp hashmap.
    071     */
    072    public static final String SKIN_ATTRIBUTE = UITool.class.getName()+ ".skin";
    073
    074    /**
    075     * The actual skin being used for the webapp.
    076     */
    077    private String skinName;
    078
    079    /**
    080     * Refresh the tool.
    081     */
    082    @Override
    083    public void refresh()
    084    {
    085        TurbineUI.refresh(getSkin());
    086        log.debug("UITool refreshed for skin: " + getSkin());
    087    }
    088
    089    /**
    090     * Provide access to the list of available skin names.
    091     *
    092     * @return the available skin names.
    093     */
    094    public String[] getSkinNames()
    095    {
    096        return TurbineUI.getSkinNames();
    097    }
    098
    099    /**
    100     * Get the name of the default skin name for the web application from the
    101     * TurbineResources.properties file. If the property is not present the
    102     * name of the default skin will be returned.  Note that the web application
    103     * skin name may be something other than default, in which case its
    104     * properties will default to the skin with the name "default".
    105     *
    106     * @return the name of the default skin for the web application.
    107     */
    108    public String getWebappSkinName()
    109    {
    110        return TurbineUI.getWebappSkinName();
    111    }
    112
    113    /**
    114     * Retrieve a skin property.  If the property is not defined in the current
    115     * skin the value for the default skin will be provided.  If the current
    116     * skin does not exist then the skin configured for the webapp will be used.
    117     * If the webapp skin does not exist the default skin will be used.  If the
    118     * default skin does not exist then <code>null</code> will be returned.
    119     *
    120     * @param key the key to retrieve from the skin.
    121     * @return the value of the property for the named skin (defaulting to the
    122     * default skin), the webapp skin, the default skin or <code>null</code>,
    123     * depending on whether or not the property or skins exist.
    124     */
    125    public String get(String key)
    126    {
    127        return TurbineUI.get(getSkin(), key);
    128    }
    129
    130    /**
    131     * Retrieve the skin name.
    132     * @return the selected skin name
    133     */
    134    public String getSkin()
    135    {
    136        return skinName;
    137    }
    138
    139    /**
    140     * Set the skin name to the skin from the TurbineResources.properties file.
    141     * If the property is not present use the "default" skin.
    142     */
    143    public void setSkin()
    144    {
    145        skinName = TurbineUI.getWebappSkinName();
    146    }
    147
    148    /**
    149     * Set the skin name to the specified skin.
    150     *
    151     * @param skinName the skin name to use.
    152     */
    153    public void setSkin(String skinName)
    154    {
    155        this.skinName = skinName;
    156    }
    157
    158    /**
    159     * Set the skin name when the tool is configured to be loaded on a
    160     * per-request basis. By default it calls getSkin to return the skin
    161     * specified in TurbineResources.properties. Developers can write a subclass
    162     * of UITool that overrides this method to determine the skin to use based
    163     * on information held in the request.
    164     *
    165     * @param data a RunData instance
    166     */
    167    protected void setSkin(RunData data)
    168    {
    169        setSkin();
    170    }
    171
    172    /**
    173     * Set the skin name when the tool is configured to be loaded on a
    174     * per-session basis. If the user's temp hashmap contains a value in the
    175     * attribute specified by the String constant SKIN_ATTRIBUTE then that is
    176     * returned. Otherwise it calls getSkin to return the skin specified in
    177     * TurbineResources.properties.
    178     *
    179     * @param user a User instance
    180     */
    181    protected void setSkin(User user)
    182    {
    183        if (user.getTemp(SKIN_ATTRIBUTE) == null)
    184        {
    185            setSkin();
    186        }
    187        else
    188        {
    189            setSkin((String) user.getTemp(SKIN_ATTRIBUTE));
    190        }
    191    }
    192
    193    /**
    194     * Set the skin name in the user's temp hashmap for the current session.
    195     *
    196     * @param user a User instance
    197     * @param skin the skin name for the session
    198     */
    199    public static void setSkin(User user, String skin)
    200    {
    201        user.setTemp(SKIN_ATTRIBUTE, skin);
    202    }
    203
    204    /**
    205     * Retrieve the URL for an image that is part of the skin. The images are
    206     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
    207     *
    208     * <p>Use this if for some reason your server name, server scheme, or server
    209     * port change on a per request basis. I'm not sure if this would happen in
    210     * a load balanced situation. I think in most cases the image(String image)
    211     * method would probably be enough, but I'm not absolutely positive.
    212     *
    213     * @param imageId the id of the image whose URL will be generated.
    214     * @param data the RunData to use as the source of the ServerData to use as
    215     * the basis for the URL.
    216     * @return the image URL
    217     */
    218    public String image(String imageId, RunData data)
    219    {
    220        return image(imageId, data.getServerData());
    221    }
    222
    223    /**
    224     * Retrieve the URL for an image that is part of the skin. The images are
    225     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
    226     *
    227     * <p>Use this if for some reason your server name, server scheme, or server
    228     * port change on a per request basis. I'm not sure if this would happen in
    229     * a load balanced situation. I think in most cases the image(String image)
    230     * method would probably be enough, but I'm not absolutely positive.
    231     *
    232     * @param imageId the id of the image whose URL will be generated.
    233     * @param serverData the serverData to use as the basis for the URL.
    234     * @return the image URL
    235     */
    236    public String image(String imageId, ServerData serverData)
    237    {
    238        return TurbineUI.image(getSkin(), imageId, serverData);
    239    }
    240
    241    /**
    242     * Retrieve the URL for an image that is part of the skin. The images are
    243     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
    244     *
    245     * @param imageId the id of the image whose URL will be generated.
    246     * @return the image URL
    247     */
    248    public String image(String imageId)
    249    {
    250        return TurbineUI.image(getSkin(), imageId);
    251    }
    252
    253    /**
    254     * Retrieve the URL for the style sheet that is part of the skin. The style
    255     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the
    256     * filename skin.css
    257     *
    258     * <p>Use this if for some reason your server name, server scheme, or server
    259     * port change on a per request basis. I'm not sure if this would happen in
    260     * a load balanced situation. I think in most cases the style() method would
    261     * probably be enough, but I'm not absolutely positive.
    262     *
    263     * @param data the RunData to use as the source of the ServerData to use as
    264     * the basis for the URL.
    265     * @return the CSS URL
    266     */
    267    public String getStylecss(RunData data)
    268    {
    269        return getStylecss(data.getServerData());
    270    }
    271
    272    /**
    273     * Retrieve the URL for the style sheet that is part of the skin. The style
    274     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the
    275     * filename skin.css
    276     *
    277     * <p>Use this if for some reason your server name, server scheme, or server
    278     * port change on a per request basis. I'm not sure if this would happen in
    279     * a load balanced situation. I think in most cases the style() method would
    280     * probably be enough, but I'm not absolutely positive.
    281     *
    282     * @param serverData the serverData to use as the basis for the URL.
    283     * @return the CSS URL
    284     */
    285    public String getStylecss(ServerData serverData)
    286    {
    287        return TurbineUI.getStylecss(getSkin(), serverData);
    288    }
    289
    290    /**
    291     * Retrieve the URL for the style sheet that is part of the skin. The style
    292     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the
    293     * filename skin.css
    294     * @return the CSS URL
    295     */
    296    public String getStylecss()
    297    {
    298        return TurbineUI.getStylecss(getSkin());
    299    }
    300
    301    /**
    302     * Retrieve the URL for a given script that is part of the skin. The script
    303     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
    304     *
    305     * <p>Use this if for some reason your server name, server scheme, or server
    306     * port change on a per request basis. I'm not sure if this would happen in
    307     * a load balanced situation. I think in most cases the image(String image)
    308     * method would probably be enough, but I'm not absolutely positive.
    309     *
    310     * @param filename the name of the script file whose URL will be generated.
    311     * @param data the RunDate to use as the source of the ServerData to use as
    312     * the basis for the URL.
    313     * @return the script URL
    314     */
    315    public String getScript(String filename, RunData data)
    316    {
    317        return getScript(filename, data.getServerData());
    318    }
    319
    320    /**
    321     * Retrieve the URL for a given script that is part of the skin. The script
    322     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
    323     *
    324     * <p>Use this if for some reason your server name, server scheme, or server
    325     * port change on a per request basis. I'm not sure if this would happen in
    326     * a load balanced situation. I think in most cases the image(String image)
    327     * method would probably be enough, but I'm not absolutely positive.
    328     *
    329     * @param filename the name of the script file whose URL will be generated.
    330     * @param serverData the serverData to use as the basis for the URL.
    331     * @return the script URL
    332     */
    333    public String getScript(String filename, ServerData serverData)
    334    {
    335        return TurbineUI.getScript(getSkin(), filename, serverData);
    336    }
    337
    338    /**
    339     * Retrieve the URL for a given script that is part of the skin. The script
    340     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
    341     *
    342     * @param filename the name of the script file whose URL will be generated.
    343     * @return the script URL
    344     */
    345    public String getScript(String filename)
    346    {
    347        return TurbineUI.getScript(getSkin(), filename);
    348    }
    349
    350    /**
    351     * Initialize the UITool object.
    352     *
    353     * @param data This is null, RunData or User depending upon specified tool
    354     * scope.
    355     */
    356    @Override
    357    public void init(Object data)
    358    {
    359        if (data == null)
    360        {
    361            log.debug("UITool scope is global");
    362            setSkin();
    363        }
    364        else if (data instanceof RunData)
    365        {
    366            log.debug("UITool scope is request");
    367            setSkin((RunData) data);
    368        }
    369        else if (data instanceof PipelineData)
    370        {
    371            PipelineData pipelineData = (PipelineData) data;
    372            RunData runData = (RunData)pipelineData;
    373            log.debug("UITool scope is request");
    374            setSkin(runData);
    375        }
    376        else if (data instanceof User)
    377        {
    378            log.debug("UITool scope is session");
    379            setSkin((User) data);
    380        }
    381    }
    382
    383}