    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.annotation.TurbineService;
    025import org.apache.turbine.om.security.User;
    026import org.apache.turbine.pipeline.PipelineData;
    027import org.apache.turbine.services.pull.ApplicationTool;
    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     * The UI service.
    081     */
    082    @TurbineService
    083    private UIService uiService;
    084
    085    /**
    086     * Refresh the tool.
    087     */
    088    @Override
    089    public void refresh()
    090    {
    091        uiService.refresh(getSkin());
    092        log.debug("UITool refreshed for skin: " + getSkin());
    093    }
    094
    095    /**
    096     * Provide access to the list of available skin names.
    097     *
    098     * @return the available skin names.
    099     */
    100    public String[] getSkinNames()
    101    {
    102        return uiService.getSkinNames();
    103    }
    104
    105    /**
    106     * Get the name of the default skin name for the web application from the
    107     * TurbineResources.properties file. If the property is not present the
    108     * name of the default skin will be returned.  Note that the web application
    109     * skin name may be something other than default, in which case its
    110     * properties will default to the skin with the name "default".
    111     *
    112     * @return the name of the default skin for the web application.
    113     */
    114    public String getWebappSkinName()
    115    {
    116        return uiService.getWebappSkinName();
    117    }
    118
    119    /**
    120     * Retrieve a skin property.  If the property is not defined in the current
    121     * skin the value for the default skin will be provided.  If the current
    122     * skin does not exist then the skin configured for the webapp will be used.
    123     * If the webapp skin does not exist the default skin will be used.  If the
    124     * default skin does not exist then <code>null</code> will be returned.
    125     *
    126     * @param key the key to retrieve from the skin.
    127     * @return the value of the property for the named skin (defaulting to the
    128     * default skin), the webapp skin, the default skin or <code>null</code>,
    129     * depending on whether or not the property or skins exist.
    130     */
    131    public String get(String key)
    132    {
    133        return uiService.get(getSkin(), key);
    134    }
    135
    136    /**
    137     * Retrieve the skin name.
    138     * @return the selected skin name
    139     */
    140    public String getSkin()
    141    {
    142        return skinName;
    143    }
    144
    145    /**
    146     * Set the skin name to the skin from the TurbineResources.properties file.
    147     * If the property is not present use the "default" skin.
    148     */
    149    public void setSkin()
    150    {
    151        skinName = uiService.getWebappSkinName();
    152    }
    153
    154    /**
    155     * Set the skin name to the specified skin.
    156     *
    157     * @param skinName the skin name to use.
    158     */
    159    public void setSkin(String skinName)
    160    {
    161        this.skinName = skinName;
    162    }
    163
    164    /**
    165     * Set the skin name when the tool is configured to be loaded on a
    166     * per-request basis. By default it calls getSkin to return the skin
    167     * specified in TurbineResources.properties. Developers can write a subclass
    168     * of UITool that overrides this method to determine the skin to use based
    169     * on information held in the request.
    170     *
    171     * @param data a RunData instance
    172     */
    173    protected void setSkin(RunData data)
    174    {
    175        setSkin();
    176    }
    177
    178    /**
    179     * Set the skin name when the tool is configured to be loaded on a
    180     * per-session basis. If the user's temp hashmap contains a value in the
    181     * attribute specified by the String constant SKIN_ATTRIBUTE then that is
    182     * returned. Otherwise it calls getSkin to return the skin specified in
    183     * TurbineResources.properties.
    184     *
    185     * @param user a User instance
    186     */
    187    protected void setSkin(User user)
    188    {
    189        if (user.getTemp(SKIN_ATTRIBUTE) == null)
    190        {
    191            setSkin();
    192        }
    193        else
    194        {
    195            setSkin((String) user.getTemp(SKIN_ATTRIBUTE));
    196        }
    197    }
    198
    199    /**
    200     * Set the skin name in the user's temp hashmap for the current session.
    201     *
    202     * @param user a User instance
    203     * @param skin the skin name for the session
    204     */
    205    public static void setSkin(User user, String skin)
    206    {
    207        user.setTemp(SKIN_ATTRIBUTE, skin);
    208    }
    209
    210    /**
    211     * Retrieve the URL for an image that is part of the skin. The images are
    212     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
    213     *
    214     * <p>Use this if for some reason your server name, server scheme, or server
    215     * port change on a per request basis. I'm not sure if this would happen in
    216     * a load balanced situation. I think in most cases the image(String image)
    217     * method would probably be enough, but I'm not absolutely positive.
    218     *
    219     * @param imageId the id of the image whose URL will be generated.
    220     * @param data the RunData to use as the source of the ServerData to use as
    221     * the basis for the URL.
    222     * @return the image URL
    223     */
    224    public String image(String imageId, RunData data)
    225    {
    226        return image(imageId, data.getServerData());
    227    }
    228
    229    /**
    230     * Retrieve the URL for an image that is part of the skin. The images are
    231     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
    232     *
    233     * <p>Use this if for some reason your server name, server scheme, or server
    234     * port change on a per request basis. I'm not sure if this would happen in
    235     * a load balanced situation. I think in most cases the image(String image)
    236     * method would probably be enough, but I'm not absolutely positive.
    237     *
    238     * @param imageId the id of the image whose URL will be generated.
    239     * @param serverData the serverData to use as the basis for the URL.
    240     * @return the image URL
    241     */
    242    public String image(String imageId, ServerData serverData)
    243    {
    244        return uiService.image(getSkin(), imageId, serverData);
    245    }
    246
    247    /**
    248     * Retrieve the URL for an image that is part of the skin. The images are
    249     * stored in the WEBAPP/resources/ui/skins/[SKIN]/images directory.
    250     *
    251     * @param imageId the id of the image whose URL will be generated.
    252     * @return the image URL
    253     */
    254    public String image(String imageId)
    255    {
    256        return uiService.image(getSkin(), imageId);
    257    }
    258
    259    /**
    260     * Retrieve the URL for the style sheet that is part of the skin. The style
    261     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the
    262     * filename skin.css
    263     *
    264     * <p>Use this if for some reason your server name, server scheme, or server
    265     * port change on a per request basis. I'm not sure if this would happen in
    266     * a load balanced situation. I think in most cases the style() method would
    267     * probably be enough, but I'm not absolutely positive.
    268     *
    269     * @param data the RunData to use as the source of the ServerData to use as
    270     * the basis for the URL.
    271     * @return the CSS URL
    272     */
    273    public String getStylecss(RunData data)
    274    {
    275        return getStylecss(data.getServerData());
    276    }
    277
    278    /**
    279     * Retrieve the URL for the style sheet that is part of the skin. The style
    280     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the
    281     * filename skin.css
    282     *
    283     * <p>Use this if for some reason your server name, server scheme, or server
    284     * port change on a per request basis. I'm not sure if this would happen in
    285     * a load balanced situation. I think in most cases the style() method would
    286     * probably be enough, but I'm not absolutely positive.
    287     *
    288     * @param serverData the serverData to use as the basis for the URL.
    289     * @return the CSS URL
    290     */
    291    public String getStylecss(ServerData serverData)
    292    {
    293        return uiService.getStylecss(getSkin(), serverData);
    294    }
    295
    296    /**
    297     * Retrieve the URL for the style sheet that is part of the skin. The style
    298     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory with the
    299     * filename skin.css
    300     * @return the CSS URL
    301     */
    302    public String getStylecss()
    303    {
    304        return uiService.getStylecss(getSkin());
    305    }
    306
    307    /**
    308     * Retrieve the URL for a given script that is part of the skin. The script
    309     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
    310     *
    311     * <p>Use this if for some reason your server name, server scheme, or server
    312     * port change on a per request basis. I'm not sure if this would happen in
    313     * a load balanced situation. I think in most cases the image(String image)
    314     * method would probably be enough, but I'm not absolutely positive.
    315     *
    316     * @param filename the name of the script file whose URL will be generated.
    317     * @param data the RunDate to use as the source of the ServerData to use as
    318     * the basis for the URL.
    319     * @return the script URL
    320     */
    321    public String getScript(String filename, RunData data)
    322    {
    323        return getScript(filename, data.getServerData());
    324    }
    325
    326    /**
    327     * Retrieve the URL for a given script that is part of the skin. The script
    328     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
    329     *
    330     * <p>Use this if for some reason your server name, server scheme, or server
    331     * port change on a per request basis. I'm not sure if this would happen in
    332     * a load balanced situation. I think in most cases the image(String image)
    333     * method would probably be enough, but I'm not absolutely positive.
    334     *
    335     * @param filename the name of the script file whose URL will be generated.
    336     * @param serverData the serverData to use as the basis for the URL.
    337     * @return the script URL
    338     */
    339    public String getScript(String filename, ServerData serverData)
    340    {
    341        return uiService.getScript(getSkin(), filename, serverData);
    342    }
    343
    344    /**
    345     * Retrieve the URL for a given script that is part of the skin. The script
    346     * is stored in the WEBAPP/resources/ui/skins/[SKIN] directory.
    347     *
    348     * @param filename the name of the script file whose URL will be generated.
    349     * @return the script URL
    350     */
    351    public String getScript(String filename)
    352    {
    353        return uiService.getScript(getSkin(), filename);
    354    }
    355
    356    /**
    357     * Initialize the UITool object.
    358     *
    359     * @param data This is null, RunData or User depending upon specified tool
    360     * scope.
    361     */
    362    @Override
    363    public void init(Object data)
    364    {
    365        if (data == null)
    366        {
    367            log.debug("UITool scope is global");
    368            setSkin();
    369        }
    370        else if (data instanceof RunData)
    371        {
    372            log.debug("UITool scope is request");
    373            setSkin((RunData) data);
    374        }
    375        else if (data instanceof PipelineData)
    376        {
    377            PipelineData pipelineData = (PipelineData) data;
    378            RunData runData = (RunData)pipelineData;
    379            log.debug("UITool scope is request");
    380            setSkin(runData);
    381        }
    382        else if (data instanceof User)
    383        {
    384            log.debug("UITool scope is session");
    385            setSkin((User) data);
    386        }
    387    }
    388
    389}