1 /*
2 * Copyright (c) 2002-2006 by OpenSymphony
3 * All rights reserved.
4 */
5
6 package com.opensymphony.xwork2.interceptor;
7
8 import java.util.Locale;
9 import java.util.Map;
10
11 import com.opensymphony.xwork2.ActionInvocation;
12 import com.opensymphony.xwork2.util.LocalizedTextUtil;
13 import com.opensymphony.xwork2.util.logging.Logger;
14 import com.opensymphony.xwork2.util.logging.LoggerFactory;
15
16 /**
17 * <!-- START SNIPPET: description -->
18 *
19 * An interceptor that handles setting the locale specified in a session as the locale for the current action request.
20 * In addition, this interceptor will look for a specific HTTP request parameter and set the locale to whatever value is
21 * provided. This means that this interceptor can be used to allow for your application to dynamically change the locale
22 * for the user's session. This is very useful for applications that require multi-lingual support and want the user to
23 * be able to set his or her language preference at any point. The locale parameter is removed during the execution of
24 * this interceptor, ensuring that properties aren't set on an action (such as request_locale) that have no typical
25 * corresponding setter in your action.
26 *
27 * <p/>For example, using the default parameter name, a request to <b>foo.action?request_locale=en_US</b>, then the
28 * locale for US English is saved in the user's session and will be used for all future requests.
29 *
30 * <!-- END SNIPPET: description -->
31 *
32 * <p/> <u>Interceptor parameters:</u>
33 *
34 * <!-- START SNIPPET: parameters -->
35 *
36 * <ul>
37 *
38 * <li>parameterName (optional) - the name of the HTTP request parameter that dictates the locale to switch to and save
39 * in the session. By default this is <b>request_locale</b></li>
40 *
41 * <li>attributeName (optional) - the name of the session key to store the selected locale. By default this is
42 * <b>WW_TRANS_I18N_LOCALE</b></li>
43 *
44 * </ul>
45 *
46 * <!-- END SNIPPET: parameters -->
47 *
48 * <p/> <u>Extending the interceptor:</u>
49 *
50 * <p/>
51 *
52 * <!-- START SNIPPET: extending -->
53 *
54 * There are no known extensions points for this interceptor.
55 *
56 * <!-- END SNIPPET: extending -->
57 *
58 * <p/> <u>Example code:</u>
59 *
60 * <pre>
61 * <!-- START SNIPPET: example -->
62 * <action name="someAction" class="com.examples.SomeAction">
63 * <interceptor-ref name="i18n"/>
64 * <interceptor-ref name="basicStack"/>
65 * <result name="success">good_result.ftl</result>
66 * </action>
67 * <!-- END SNIPPET: example -->
68 * </pre>
69 *
70 * @author Aleksei Gopachenko
71 */
72 public class I18nInterceptor extends AbstractInterceptor {
73 protected static final Logger LOG = LoggerFactory.getLogger(I18nInterceptor.class);
74
75 public static final String DEFAULT_SESSION_ATTRIBUTE = "WW_TRANS_I18N_LOCALE";
76 public static final String DEFAULT_PARAMETER = "request_locale";
77
78 protected String parameterName = DEFAULT_PARAMETER;
79 protected String attributeName = DEFAULT_SESSION_ATTRIBUTE;
80
81 public I18nInterceptor() {
82 if (LOG.isDebugEnabled()) {
83 LOG.debug("new I18nInterceptor()");
84 }
85 }
86
87 public void setParameterName(String parameterName) {
88 this.parameterName = parameterName;
89 }
90
91 public void setAttributeName(String attributeName) {
92 this.attributeName = attributeName;
93 }
94
95 public String intercept(ActionInvocation invocation) throws Exception {
96 if (LOG.isDebugEnabled()) {
97 LOG.debug("intercept '"
98 + invocation.getProxy().getNamespace() + "/"
99 + invocation.getProxy().getActionName() + "' { ");
100 }
101 //get requested locale
102 Map params = invocation.getInvocationContext().getParameters();
103 Object requested_locale = params.remove(parameterName);
104 if (requested_locale != null && requested_locale.getClass().isArray()
105 && ((Object[]) requested_locale).length == 1) {
106 requested_locale = ((Object[]) requested_locale)[0];
107 }
108
109 if (LOG.isDebugEnabled()) {
110 LOG.debug("requested_locale=" + requested_locale);
111 }
112
113 //save it in session
114 Map session = invocation.getInvocationContext().getSession();
115 if (session != null) {
116 if (requested_locale != null) {
117 Locale locale = (requested_locale instanceof Locale) ?
118 (Locale) requested_locale : LocalizedTextUtil.localeFromString(requested_locale.toString(), null);
119 if (LOG.isDebugEnabled()) {
120 LOG.debug("store locale=" + locale);
121 }
122
123 if (locale != null) {
124 session.put(attributeName, locale);
125 }
126 }
127
128 //set locale for action
129 Object locale = session.get(attributeName);
130 if (locale != null && locale instanceof Locale) {
131 if (LOG.isDebugEnabled()) {
132 LOG.debug("apply locale=" + locale);
133 }
134
135 saveLocale(invocation, (Locale)locale);
136 }
137 }
138
139 if (LOG.isDebugEnabled()) {
140 LOG.debug("before Locale=" + invocation.getStack().findValue("locale"));
141 }
142
143 final String result = invocation.invoke();
144 if (LOG.isDebugEnabled()) {
145 LOG.debug("after Locale=" + invocation.getStack().findValue("locale"));
146 }
147
148 if (LOG.isDebugEnabled()) {
149 LOG.debug("intercept } ");
150 }
151
152 return result;
153 }
154
155 /**
156 * Save the given locale to the ActionInvocation.
157 *
158 * @param invocation The ActionInvocation.
159 * @param locale The locale to save.
160 */
161 protected void saveLocale(ActionInvocation invocation, Locale locale) {
162 invocation.getInvocationContext().setLocale(locale);
163 }
164
165 }