/* * 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. */ package org.apache.cocoon.acting; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.cocoon.environment.Redirector; import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.i18n.I18nUtils; import java.util.HashMap; import java.util.Locale; import java.util.Map; /** * An action that locates and provides to the pipeline locale information * looked up in a range of ways. * * <h1>Configuration</h1> * <p>A sample configuration (given in the <map:matchers> section of the * sitemap) is given below. This configuration shows default values. * </p> * <pre> * <map:action name="locale" src="org.apache.cocoon.acting.LocaleAction"> * <locale-attribute>locale</locale-attribute> * <use-locale>true</use-locale> * <default-locale language="en" country="US"/> * <store-in-request>false<store-in-request> * <create-session>false<create-session> * <store-in-session>false<store-in-session> * <store-in-cookie>false<store-in-cookie> * </map:action> * </pre> * * <p>Above configuration parameters mean: * <ul> * <li><b>locale-attribute</b> specifies the name of the request * parameter / session attribute / cookie that is to be used as a locale * (defaults to <code>locale</code>)</li> * <li><b>use-locale</b> specifies whether the primary locale provided * by the user agent (or server default, is no locale passed by the agent) * is to be used</li> * <li><b>default-locale</b> specifies the default locale to be used when * none found.</li> * <li><b>store-in-request</b> specifies whether found locale should be * stored as request attribute.</li> * <li><b>create-session</b> specifies whether session should be created * when storing found locale as session attribute.</li> * <li><b>store-in-session</b> specifies whether found locale should be * stored as session attribute.</li> * <li><b>store-in-cookie</b> specifies whether found locale should be * stored as cookie.</li> * </ul> * </p> * * <h1>Usage</h1> * <p>This action will be used in a pipeline like so:</p> * <pre> * <map:act type="locale"> * <map:generate src="file_{language}_{country}_{variant}.xml"/> * ... * </map:match> * </pre> * <p>or</p> * <pre> * <map:act type="locale"> * <map:generate src="file_{locale}.xml"/> * ... * </map:match> * </pre> * * <h1>Locale Identification</h1> * <p>Locales will be tested in following order:</p> * <ul> * <li>Locale provided as a request parameter</li> * <li>Locale provided as a session attribute</li> * <li>Locale provided as a cookie</li> * <li>Locale provided using a sitemap parameter<br> * (<map:parameter name="locale" value="{1}"/> style parameter within * the <map:match> node)</li> * <li>Locale provided by the user agent, or server default, * if <code>use-locale</code> is set to <code>true</code></li> * <li>The default locale, if specified in the matcher's configuration</li> * </ul> * <p>First found locale will be returned.</p> * * <h1>Sitemap Variables</h1> * <p>Once locale has been found, the following sitemap variables * will be available to sitemap elements contained within the action:</p> * <ul> * <li>{locale}: The locale string</li> * <li>{language}: The language of the found locale</li> * <li>{country}: The country of the found locale</li> * <li>{variant}: The variant of the found locale</li> * </ul> * * @author <a href="mailto:Marcus.Crafter@osa.de">Marcus Crafter</a> * @author <a href="mailto:kpiroumian@flagship.ru">Konstantin Piroumian</a> * @author <a href="mailto:lassi.immonen@valkeus.com">Lassi Immonen</a> * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a> * @version CVS $Id$ */ public class LocaleAction extends ServiceableAction implements ThreadSafe, Configurable { private static final String DEFAULT_DEFAULT_LANG = "en"; private static final String DEFAULT_DEFAULT_COUNTRY = "US"; private static final String DEFAULT_DEFAULT_VARIANT = ""; /** * Default locale attribute name. */ public static final String LOCALE = "locale"; /** * Configuration element name for locale attribute name. */ public static final String LOCALE_ATTR = "locale-attribute"; /** * Constant representing the request storage configuration attribute */ public static final String STORE_REQUEST = "store-in-request"; /** * Constant representing the session creation configuration attribute */ public static final String CREATE_SESSION = "create-session"; /** * Constant representing the session storage configuration attribute */ public static final String STORE_SESSION = "store-in-session"; /** * Constant representing the cookie storage configuration attribute */ public static final String STORE_COOKIE = "store-in-cookie"; /** * Name of the locale request parameter, session attribute, cookie. */ private String localeAttribute; /** * Whether to query locale provided by the user agent or not. */ private boolean useLocale; /** * Default locale if no other found and {@link #useLocale} is false. */ private Locale defaultLocale; /** * Store the locale in request. Default is not to do this. */ private boolean storeInRequest; /** * Store the locale in session, if available. Default is not to do this. */ private boolean storeInSession; /** * Should we create a session if needed. Default is not to do this. */ private boolean createSession; /** * Should we add a cookie with the locale. Default is not to do this. */ private boolean storeInCookie; /** * Configure this action. * * @param config configuration information (if any) */ public void configure(Configuration config) throws ConfigurationException { this.storeInRequest = config.getChild(STORE_REQUEST).getValueAsBoolean(false); this.createSession = config.getChild(CREATE_SESSION).getValueAsBoolean(false); this.storeInSession = config.getChild(STORE_SESSION).getValueAsBoolean(false); this.storeInCookie = config.getChild(STORE_COOKIE).getValueAsBoolean(false); if (getLogger().isDebugEnabled()) { getLogger().debug((this.storeInRequest ? "will" : "won't") + " set values in request"); getLogger().debug((this.createSession ? "will" : "won't") + " create session"); getLogger().debug((this.storeInSession ? "will" : "won't") + " set values in session"); getLogger().debug((this.storeInCookie ? "will" : "won't") + " set values in cookies"); } this.localeAttribute = config.getChild(LOCALE_ATTR).getValue(LOCALE); this.useLocale = config.getChild("use-locale").getValueAsBoolean(true); Configuration child = config.getChild("default-locale", false); if (child != null) { this.defaultLocale = new Locale(child.getAttribute("language", DEFAULT_DEFAULT_LANG), child.getAttribute("country", DEFAULT_DEFAULT_COUNTRY), child.getAttribute("variant", DEFAULT_DEFAULT_VARIANT)); } if (getLogger().isDebugEnabled()) { getLogger().debug("Locale attribute name is " + this.localeAttribute); getLogger().debug((this.useLocale ? "will" : "won't") + " use request locale"); getLogger().debug("default locale " + this.defaultLocale); } } /** * Action which obtains the current environments locale information, and * places it in the objectModel (and optionally in a session/cookie). */ public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters params) throws Exception { // Obtain locale information from request, session, cookies, or params Locale locale = I18nUtils.findLocale(objectModel, localeAttribute, params, defaultLocale, useLocale); if (locale == null) { if (getLogger().isDebugEnabled()) { getLogger().debug("No locale found."); } return null; } String localeStr = locale.toString(); if (getLogger().isDebugEnabled()) { getLogger().debug("Found locale: " + localeStr); } I18nUtils.storeLocale(objectModel, localeAttribute, localeStr, storeInRequest, storeInSession, storeInCookie, createSession); // Set up a map for sitemap parameters Map map = new HashMap(); map.put("language", locale.getLanguage()); map.put("country", locale.getCountry()); map.put("variant", locale.getVariant()); map.put("locale", localeStr); return map; } /** * Helper method to retreive the attribute value containing locale * information. See class documentation for locale determination algorythm. * * @deprecated See I18nUtils.findLocale * @param objectModel requesting object's environment * @return locale value or <code>null</null> if no locale was found */ public static String getLocaleAttribute(Map objectModel, String localeAttrName) { Locale locale = I18nUtils.findLocale(objectModel, localeAttrName, null, null, true); return locale.toString(); } }