| package org.apache.turbine.services.ui; |
| |
| /* |
| * Copyright 2003-2004 The Apache Software Foundation. |
| * |
| * Licensed 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.FileInputStream; |
| import java.io.FilenameFilter; |
| import java.util.HashMap; |
| import java.util.Properties; |
| |
| 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.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. |
| * |
| * @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 org.apache.commons.logging.Log log = |
| org.apache.commons.logging.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 skin that is to be used for the web application. |
| */ |
| private static final String SKIN_PROPERTY_KEY = "tool.ui.skin"; |
| |
| /** |
| * 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 static final String skinsDirectory |
| = TurbinePull.getAbsolutePathToResourcesDirectory() |
| + SKINS_DIRECTORY; |
| |
| /** |
| * 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 SKIN_CSS_FILE = "skin.css"; |
| |
| /** |
| * The directory where application tool resources are stored. |
| */ |
| private static String resourcesDirectory; |
| |
| /** |
| * 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); |
| } |
| |
| /** |
| * 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. |
| * |
| * @param skinName the name of the skin whose Properties is to be retrieved. |
| * @return the properties for the named skin, the webapp skin, the default |
| * skin or an empty Properties, depending on which skins exist. |
| */ |
| private synchronized Properties loadSkin(String skinName) |
| { |
| Properties defaultSkinProperties = null; |
| |
| if (!skinName.equals(SKIN_PROPERTY_DEFAULT)) |
| { |
| defaultSkinProperties = getSkinProperties(SKIN_PROPERTY_DEFAULT); |
| } |
| |
| // The following line is okay even for default. |
| Properties skinProperties = new Properties(defaultSkinProperties); |
| |
| try |
| { |
| log.debug("Loading selected skin from: " + skinsDirectory + "/" |
| + skinName + "/" + SKIN_PROPS_FILE); |
| FileInputStream is = new FileInputStream( |
| skinsDirectory + "/" + skinName + "/" + SKIN_PROPS_FILE); |
| |
| skinProperties.load(is); |
| } |
| catch (Exception e) |
| { |
| log.error("Cannot load skin: " + skinName, e); |
| if (!skinName.equals(getWebappSkinName()) |
| && !skinName.equals(SKIN_PROPERTY_DEFAULT)) |
| { |
| log.error("Attempting to return the skin configured for " |
| + "webapp instead of " + skinName); |
| return getSkinProperties(getWebappSkinName()); |
| } |
| else if (!skinName.equals(SKIN_PROPERTY_DEFAULT)) |
| { |
| log.error("Attempting to return the default skin instead of " |
| + skinName); |
| return getSkinProperties(SKIN_PROPERTY_DEFAULT); |
| } |
| 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.propertiess 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_KEY, 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 happend 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) |
| { |
| DataURI du = new DataURI(serverData); |
| |
| StringBuffer sb = new StringBuffer(); |
| |
| sb.append(resourcesDirectory). |
| append(SKINS_DIRECTORY). |
| append("/"). |
| append(skinName). |
| append(IMAGES_DIRECTORY). |
| append("/"). |
| append(imageId); |
| |
| du.setScriptName(sb.toString()); |
| return du.getAbsoluteLink(); |
| } |
| |
| /** |
| * 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) |
| { |
| ServerData sd = Turbine.getDefaultServerData(); |
| DataURI du = new DataURI(sd); |
| |
| StringBuffer sb = new StringBuffer(); |
| |
| sb.append(resourcesDirectory). |
| append(SKINS_DIRECTORY). |
| append("/"). |
| append(skinName). |
| append(IMAGES_DIRECTORY). |
| append("/"). |
| append(imageId); |
| |
| du.setScriptName(sb.toString()); |
| return du.getAbsoluteLink(); |
| } |
| |
| /** |
| * 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 happend 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) |
| { |
| DataURI du = new DataURI(serverData); |
| StringBuffer sb = new StringBuffer(); |
| |
| sb.append(resourcesDirectory). |
| append(SKINS_DIRECTORY). |
| append("/"). |
| append(skinName). |
| append("/"). |
| append(SKIN_CSS_FILE); |
| |
| du.setScriptName(sb.toString()); |
| return du.getAbsoluteLink(); |
| } |
| |
| /** |
| * 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) |
| { |
| ServerData sd = Turbine.getDefaultServerData(); |
| DataURI du = new DataURI(sd); |
| |
| StringBuffer sb = new StringBuffer(); |
| |
| sb.append(resourcesDirectory). |
| append(SKINS_DIRECTORY). |
| append("/"). |
| append(skinName). |
| append("/"). |
| append(SKIN_CSS_FILE); |
| |
| du.setScriptName(sb.toString()); |
| return du.getAbsoluteLink(); |
| } |
| |
| // ---- Service initilization ------------------------------------------ |
| |
| /** |
| * Initializes the service. |
| */ |
| public void init() throws InitializationException |
| { |
| // Ensure PullService has been initialised. |
| getServiceBroker().initService("PullService"); |
| |
| // Get the resources directory that is specificed in the TR.props or |
| // default to "resources", relative to the webapp. |
| resourcesDirectory = TurbinePull.getResourcesDirectory(); |
| |
| setInit(true); |
| } |
| |
| /** |
| * Returns to uninitialized state. |
| */ |
| public void shutdown() |
| { |
| clearSkins(); |
| |
| setInit(false); |
| } |
| |
| } |