blob: 201b9a6d0de75c613c60b076a40bc83ba80f4c1d [file] [log] [blame]
/*
* 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 &lt;map:matchers&gt; section of the
* sitemap) is given below. This configuration shows default values.
* </p>
* <pre>
* &lt;map:action name="locale" src="org.apache.cocoon.acting.LocaleAction"&gt;
* &lt;locale-attribute&gt;locale&lt;/locale-attribute&gt;
* &lt;use-locale&gt;true&lt;/use-locale&gt;
* &lt;default-locale language="en" country="US"/&gt;
* &lt;store-in-request&gt;false&lt;store-in-request&gt;
* &lt;create-session&gt;false&lt;create-session&gt;
* &lt;store-in-session&gt;false&lt;store-in-session&gt;
* &lt;store-in-cookie&gt;false&lt;store-in-cookie&gt;
* &lt;/map:action&gt;
* </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>
* &lt;map:act type="locale"&gt;
* &lt;map:generate src="file_{language}_{country}_{variant}.xml"/&gt;
* ...
* &lt;/map:match&gt;
* </pre>
* <p>or</p>
* <pre>
* &lt;map:act type="locale"&gt;
* &lt;map:generate src="file_{locale}.xml"/&gt;
* ...
* &lt;/map:match&gt;
* </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>
* (&lt;map:parameter name="locale" value="{1}"/&gt; style parameter within
* the &lt;map:match&gt; 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();
}
}