Author: grobmeier
Date: Mon Jul 15 10:06:07 2013
New Revision: 1503160

URL: http://svn.apache.org/r1503160
Log:
WW-4141: Added support for saving locale in cookie

Added:
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/interceptor/I18nInterceptor.java
   (with props)
    
struts/struts2/trunk/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java
   (with props)
Modified:
    
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/I18nInterceptor.java

Added: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/interceptor/I18nInterceptor.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/interceptor/I18nInterceptor.java?rev=1503160&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/interceptor/I18nInterceptor.java
 (added)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/interceptor/I18nInterceptor.java
 Mon Jul 15 10:06:07 2013
@@ -0,0 +1,176 @@
+/*
+ * $Id$
+ *
+ * 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.struts2.interceptor;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsStatics;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * <!-- START SNIPPET: description -->
+ * This interceptor extends the original xwork i18n interceptor
+ * and adds functionality to support cookies.
+ *
+ * <!-- END SNIPPET: description -->
+ *
+ * <!-- START SNIPPET: parameters -->
+  * <p/>
+  * <ul>
+  * <p/>
+  * <li>parameterName (optional) - the name of the HTTP request parameter that 
dictates the locale to switch to and save
+  * in the session. By default this is <b>request_locale</b></li>
+  * <p/>
+  * <li>requestCookieParameterName (optional) - the name of the HTTP request 
parameter that dictates the locale to switch to
+  * and save in a cookien. By default this is <b>request_cookie_locale</b></li>
+  * <p/>
+  * <li>requestOnlyParameterName (optional) - the name of the HTTP request 
parameter that dictates the locale to switch to
+  * for the current request only, without saving it in the session. By default 
this is <b>request_only_locale</b></li>
+  * <p/>
+  * <li>attributeName (optional) - the name of the session key to store the 
selected locale. By default this is
+  * <b>WW_TRANS_I18N_LOCALE</b></li>
+  * <p/>
+  * </ul>
+  * <p/>
+  * <!-- END SNIPPET: parameters -->
+  *
+  * <!-- START SNIPPET: example -->
+  * &lt;interceptor name="i18nCookie" 
class="org.apache.struts2.interceptor.I18nInterceptor"/&gt;
+  *
+  * &lt;action name="someAction" class="com.examples.SomeAction"&gt;
+  *     &lt;interceptor-ref name="i18nCookie"/&gt;
+  *     &lt;interceptor-ref name="basicStack"/&gt;
+  *     &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
+  * &lt;/action&gt;
+  * <!-- END SNIPPET: example -->
+  */
+public class I18nInterceptor extends 
com.opensymphony.xwork2.interceptor.I18nInterceptor {
+    private static final long serialVersionUID = 4587460933182760358L;
+
+    public static final String DEFAULT_COOKIE_ATTRIBUTE = 
DEFAULT_SESSION_ATTRIBUTE;
+
+    public static final String COOKIE_STORAGE = "cookie";
+
+    public static final String DEFAULT_COOKIE_PARAMETER = 
"request_cookie_locale";
+    protected String requestCookieParameterName = DEFAULT_COOKIE_PARAMETER;
+
+    protected class CookieLocaleFinder extends LocaleFinder {
+        protected CookieLocaleFinder(ActionInvocation invocation) {
+            super(invocation);
+        }
+
+        @Override
+        protected void find() {
+            //get requested locale
+            Map<String, Object> params = 
actionInvocation.getInvocationContext().getParameters();
+            storage = Storage.SESSION.toString();
+
+            requestedLocale = findLocaleParameter(params, parameterName);
+
+            if (requestedLocale != null) {
+                return;
+            }
+
+            requestedLocale = findLocaleParameter(params, 
requestCookieParameterName);
+            if (requestedLocale != null) {
+                storage = COOKIE_STORAGE;
+                return;
+            }
+
+            requestedLocale = findLocaleParameter(params, 
requestOnlyParameterName);
+            if (requestedLocale != null) {
+                storage = Storage.NONE.toString();
+            }
+
+        }
+    }
+
+    @Override
+    public String intercept(ActionInvocation invocation) throws Exception {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("intercept '#0/#1' {",
+                invocation.getProxy().getNamespace(), 
invocation.getProxy().getActionName());
+        }
+
+        LocaleFinder localeFinder = new CookieLocaleFinder(invocation);
+        Locale locale = getLocaleFromParam(localeFinder.getRequestedLocale());
+        locale = storeLocale(invocation, locale, localeFinder.getStorage());
+        saveLocale(invocation, locale);
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("before Locale=#0", 
invocation.getStack().findValue("locale"));
+        }
+
+        final String result = invocation.invoke();
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("after Locale=#0", 
invocation.getStack().findValue("locale"));
+            LOG.debug("intercept } ");
+        }
+
+        return result;
+    }
+
+    @Override
+    protected Locale storeLocale(ActionInvocation invocation, Locale locale, 
String storage) {
+        if (COOKIE_STORAGE.equals(storage)) {
+            ActionContext ac = invocation.getInvocationContext();
+            HttpServletResponse response = (HttpServletResponse) 
ac.get(StrutsStatics.HTTP_RESPONSE);
+
+            Cookie cookie = new Cookie(DEFAULT_COOKIE_ATTRIBUTE, 
locale.toString());
+            cookie.setMaxAge(1209600); // two weeks
+            response.addCookie(cookie);
+
+            storage = Storage.SESSION.toString();
+        }
+
+        return super.storeLocale(invocation, locale, storage);
+    }
+
+    @Override
+    protected Locale readStoredLocale(ActionInvocation invocation, Map<String, 
Object> session) {
+        Locale locale = this.readStoredLocalFromSession(invocation, session);
+
+        if (locale != null) {
+            return locale;
+        }
+
+        Cookie[] cookies = ServletActionContext.getRequest().getCookies();
+        if (cookies != null) {
+            for (Cookie cookie : cookies) {
+                if (DEFAULT_COOKIE_ATTRIBUTE.equals(cookie.getName())) {
+                    return getLocaleFromParam(cookie.getValue());
+                }
+            }
+        }
+
+        return this.readStoredLocalFromCurrentInvocation(invocation);
+    }
+
+    public void setRequestCookieParameterName(String 
requestCookieParameterName) {
+        this.requestCookieParameterName = requestCookieParameterName;
+    }
+}

Propchange: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/interceptor/I18nInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java?rev=1503160&view=auto
==============================================================================
--- 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java
 (added)
+++ 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java
 Mon Jul 15 10:06:07 2013
@@ -0,0 +1,264 @@
+/*
+ * $Id$
+ *
+ * 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.struts2.interceptor;
+
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.mock.MockActionInvocation;
+import org.apache.struts2.StrutsStatics;
+import org.easymock.EasyMock;
+import org.easymock.IArgumentMatcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.jmock.expectation.AssertMo.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class I18nInterceptorTest {
+    private I18nInterceptor interceptor;
+    private ActionInvocation mai;
+    private ActionContext ac;
+    private Map<String, Object> params;
+    private Map session;
+
+    @Before
+    public void setUp() throws Exception {
+        interceptor = new I18nInterceptor();
+        interceptor.init();
+        params = new HashMap<String, Object>();
+        session = new HashMap();
+
+        Map<String, Object> ctx = new HashMap<String, Object>();
+        ctx.put(ActionContext.PARAMETERS, params);
+        ctx.put(ActionContext.SESSION, session);
+        ac = new ActionContext(ctx);
+
+        Action action = new Action() {
+            public String execute() throws Exception {
+                return SUCCESS;
+            }
+        };
+        mai = new MockActionInvocation();
+        ((MockActionInvocation) mai).setAction(action);
+        ((MockActionInvocation) mai).setInvocationContext(ac);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        interceptor.destroy();
+        interceptor = null;
+        ac = null;
+        params = null;
+        session = null;
+        mai = null;
+    }
+
+    static class CookieMatcher implements IArgumentMatcher {
+        private Cookie expected;
+
+        CookieMatcher(Cookie cookie) {
+            expected = cookie;
+        }
+
+        public boolean matches(Object argument) {
+            Cookie cookie = ((Cookie) argument);
+            return
+                (cookie.getName().equals(expected.getName()) &&
+                 cookie.getValue().equals(expected.getValue()));
+        }
+
+        public static Cookie eqCookie(Cookie ck) {
+            EasyMock.reportMatcher(new CookieMatcher(ck));
+            return null;
+        }
+
+        public void appendTo(StringBuffer buffer) {
+            buffer
+                .append("Received")
+                .append(expected.getName())
+                .append("/")
+                .append(expected.getValue());
+        }
+    }
+
+    @Test
+    public void testCookieCreation() throws Exception {
+
+        params.put(I18nInterceptor.DEFAULT_COOKIE_PARAMETER, "da_DK");
+
+        final Cookie cookie = new 
Cookie(I18nInterceptor.DEFAULT_COOKIE_ATTRIBUTE, "da_DK");
+
+        HttpServletResponse response = 
EasyMock.createMock(HttpServletResponse.class);
+        response.addCookie(CookieMatcher.eqCookie(cookie));
+        EasyMock.replay(response);
+
+        ac.put(StrutsStatics.HTTP_RESPONSE, response);
+        interceptor.intercept(mai);
+
+        EasyMock.verify(response);
+
+        Locale denmark = new Locale("da", "DK");
+        assertNotNull(session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); 
// should be stored here
+        assertEquals(denmark, 
session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); // should create a 
locale object
+    }
+
+    @Test
+    public void testNoSession() throws Exception {
+        ac.setSession(null);
+        interceptor.intercept(mai);
+    }
+
+    @Test
+    public void testDefaultLocale() throws Exception {
+        params.put(I18nInterceptor.DEFAULT_PARAMETER, "_"); // bad locale that 
would get us default locale instead
+        interceptor.intercept(mai);
+
+        assertNull(params.get(I18nInterceptor.DEFAULT_PARAMETER)); // should 
have been removed
+
+        assertNotNull(session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); 
// should be stored here
+        assertEquals(Locale.getDefault(), 
session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); // should create a 
locale object
+    }
+
+    @Test
+    public void testDenmarkLocale() throws Exception {
+        params.put(I18nInterceptor.DEFAULT_PARAMETER, "da_DK");
+        interceptor.intercept(mai);
+
+        assertNull(params.get(I18nInterceptor.DEFAULT_PARAMETER)); // should 
have been removed
+
+        Locale denmark = new Locale("da", "DK");
+        assertNotNull(session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); 
// should be stored here
+        assertEquals(denmark, 
session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); // should create a 
locale object
+    }
+
+    @Test
+    public void testDenmarkLocaleRequestOnly() throws Exception {
+        params.put(I18nInterceptor.DEFAULT_REQUESTONLY_PARAMETER, "da_DK");
+        interceptor.intercept(mai);
+
+        assertNull(params.get(I18nInterceptor.DEFAULT_PARAMETER)); // should 
have been removed
+
+        Locale denmark = new Locale("da", "DK");
+        assertNull(session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); // 
should be stored here
+        assertEquals(denmark, mai.getInvocationContext().getLocale()); // 
should create a locale object
+    }
+
+    @Test
+    public void testCountryOnlyLocale() throws Exception {
+        params.put(I18nInterceptor.DEFAULT_PARAMETER, "DK");
+        interceptor.intercept(mai);
+
+        assertNull(params.get(I18nInterceptor.DEFAULT_PARAMETER)); // should 
have been removed
+
+        Locale denmark = new Locale("DK");
+        assertNotNull(session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); 
// should be stored here
+        assertEquals(denmark, 
session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); // should create a 
locale object
+    }
+
+    @Test
+    public void testLanguageOnlyLocale() throws Exception {
+        params.put(I18nInterceptor.DEFAULT_PARAMETER, "da_");
+        interceptor.intercept(mai);
+
+        assertNull(params.get(I18nInterceptor.DEFAULT_PARAMETER)); // should 
have been removed
+
+        Locale denmark = new Locale("da");
+        assertNotNull(session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); 
// should be stored here
+        assertEquals(denmark, 
session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); // should create a 
locale object
+    }
+
+    @Test
+    public void testWithVariant() throws Exception {
+        params.put(I18nInterceptor.DEFAULT_PARAMETER, "fr_CA_xx");
+        interceptor.intercept(mai);
+
+        assertNull(params.get(I18nInterceptor.DEFAULT_PARAMETER)); // should 
have been removed
+
+        Locale variant = new Locale("fr", "CA", "xx");
+        Locale locale = (Locale) 
session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE);
+        assertNotNull(locale); // should be stored here
+        assertEquals(variant, locale);
+        assertEquals("xx", locale.getVariant());
+    }
+
+    @Test
+    public void testWithVariantRequestOnly() throws Exception {
+        params.put(I18nInterceptor.DEFAULT_REQUESTONLY_PARAMETER, "fr_CA_xx");
+        interceptor.intercept(mai);
+
+        assertNull(params.get(I18nInterceptor.DEFAULT_PARAMETER)); // should 
have been removed
+        assertNull(session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE));
+
+        Locale variant = new Locale("fr", "CA", "xx");
+        Locale locale = mai.getInvocationContext().getLocale();
+        assertNotNull(locale); // should be stored here
+        assertEquals(variant, locale);
+        assertEquals("xx", locale.getVariant());
+    }
+
+    @Test
+    public void testRealLocaleObjectInParams() throws Exception {
+        params.put(I18nInterceptor.DEFAULT_PARAMETER, Locale.CANADA_FRENCH);
+        interceptor.intercept(mai);
+
+        assertNull(params.get(I18nInterceptor.DEFAULT_PARAMETER)); // should 
have been removed
+
+        assertNotNull(session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); 
// should be stored here
+        assertEquals(Locale.CANADA_FRENCH, 
session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); // should create a 
locale object
+    }
+
+    @Test
+    public void testRealLocalesInParams() throws Exception {
+        Locale[] locales = new Locale[]{Locale.CANADA_FRENCH};
+        assertTrue(locales.getClass().isArray());
+        params.put(I18nInterceptor.DEFAULT_PARAMETER, locales);
+        interceptor.intercept(mai);
+
+        assertNull(params.get(I18nInterceptor.DEFAULT_PARAMETER)); // should 
have been removed
+
+        assertNotNull(session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE)); 
// should be stored here
+        assertEquals(Locale.CANADA_FRENCH, 
session.get(I18nInterceptor.DEFAULT_SESSION_ATTRIBUTE));
+    }
+
+    @Test
+    public void testSetParameterAndAttributeNames() throws Exception {
+        interceptor.setAttributeName("hello");
+        interceptor.setParameterName("world");
+
+        params.put("world", Locale.CHINA);
+        interceptor.intercept(mai);
+
+        assertNull(params.get("world")); // should have been removed
+
+        assertNotNull(session.get("hello")); // should be stored here
+        assertEquals(Locale.CHINA, session.get("hello"));
+    }
+}

Propchange: 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/interceptor/I18nInterceptorTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/I18nInterceptor.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/I18nInterceptor.java?rev=1503160&r1=1503159&r2=1503160&view=diff
==============================================================================
--- 
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/I18nInterceptor.java
 (original)
+++ 
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/I18nInterceptor.java
 Mon Jul 15 10:06:07 2013
@@ -97,6 +97,9 @@ public class I18nInterceptor extends Abs
     protected String requestOnlyParameterName = DEFAULT_REQUESTONLY_PARAMETER;
     protected String attributeName = DEFAULT_SESSION_ATTRIBUTE;
 
+    // Request-Only = None
+    protected enum Storage { SESSION, NONE }
+
     public I18nInterceptor() {
         if (LOG.isDebugEnabled()) {
             LOG.debug("new I18nInterceptor()");
@@ -121,50 +124,107 @@ public class I18nInterceptor extends Abs
             LOG.debug("intercept '#0/#1' {",
                 invocation.getProxy().getNamespace(), 
invocation.getProxy().getActionName());
         }
-        //get requested locale
-        Map<String, Object> params = 
invocation.getInvocationContext().getParameters();
 
-        boolean storeInSession = true;
+        LocaleFinder localeFinder = new LocaleFinder(invocation);
+        Locale locale = getLocaleFromParam(localeFinder.getRequestedLocale());
+        locale = storeLocale(invocation, locale, localeFinder.getStorage());
+        saveLocale(invocation, locale);
 
-        Object requestedLocale = findLocaleParameter(params, parameterName);
-        if (requestedLocale == null) {
-            requestedLocale = findLocaleParameter(params, 
requestOnlyParameterName);
-            if (requestedLocale != null) {
-                storeInSession = false;
-            }
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("before Locale=#0", 
invocation.getStack().findValue("locale"));
         }
 
-        Locale locale = getLocaleFromParam(requestedLocale);
+        final String result = invocation.invoke();
 
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("after Locale=#0", 
invocation.getStack().findValue("locale"));
+            LOG.debug("intercept } ");
+        }
+
+        return result;
+    }
+
+    /**
+     * Store the locale to the chosen storage, like f. e. the session
+     *
+     * @param invocation the action invocation
+     * @param locale the locale to store
+     * @param storage the place to store this locale (like 
Storage.SESSSION.toString())
+     */
+    protected Locale storeLocale(ActionInvocation invocation, Locale locale, 
String storage) {
         //save it in session
         Map<String, Object> session = 
invocation.getInvocationContext().getSession();
 
         if (session != null) {
             synchronized (session) {
                 if (locale == null) {
-                    storeInSession = false;
+                    storage = Storage.NONE.toString();
                     locale = readStoredLocale(invocation, session);
                 }
 
-                if (storeInSession) {
+                if (Storage.SESSION.toString().equals(storage)) {
                     session.put(attributeName, locale);
                 }
             }
         }
+        return locale;
+    }
 
-        saveLocale(invocation, locale);
+    protected class LocaleFinder {
+        protected String storage = Storage.SESSION.toString();
+        protected Object requestedLocale = null;
 
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("before Locale=#0", 
invocation.getStack().findValue("locale"));
+        protected ActionInvocation actionInvocation = null;
+
+        protected LocaleFinder(ActionInvocation invocation) {
+            actionInvocation = invocation;
+            find();
         }
 
-        final String result = invocation.invoke();
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("after Locale=#0", 
invocation.getStack().findValue("locale"));
-            LOG.debug("intercept } ");
+        protected void find() {
+            //get requested locale
+            Map<String, Object> params = 
actionInvocation.getInvocationContext().getParameters();
+
+            storage = Storage.SESSION.toString();
+
+            requestedLocale = findLocaleParameter(params, parameterName);
+            if (requestedLocale != null) {
+                return;
+            }
+
+            requestedLocale = findLocaleParameter(params, 
requestOnlyParameterName);
+            if (requestedLocale != null) {
+                storage = Storage.NONE.toString();
+            }
         }
 
-        return result;
+        public String getStorage() {
+            return storage;
+        }
+
+        public Object getRequestedLocale() {
+            return requestedLocale;
+        }
+    }
+
+    /**
+     * Creates a Locale object from the request param, which might
+     * be already a Local or a String
+     *
+     * @param requestedLocale the parameter from the request
+     * @return the Locale
+     */
+    protected Locale getLocaleFromParam(Object requestedLocale) {
+        Locale locale = null;
+        if (requestedLocale != null) {
+            locale = (requestedLocale instanceof Locale) ?
+                    (Locale) requestedLocale :
+                    
LocalizedTextUtil.localeFromString(requestedLocale.toString(), null);
+            if (locale != null && LOG.isDebugEnabled()) {
+                LOG.debug("applied request locale=#0", locale);
+            }
+        }
+        return locale;
     }
 
     /**
@@ -176,7 +236,17 @@ public class I18nInterceptor extends Abs
      * @return the read locale
      */
     protected Locale readStoredLocale(ActionInvocation invocation, Map<String, 
Object> session) {
-        // check session for saved locale
+        Locale locale = this.readStoredLocalFromSession(invocation, session);
+
+        if (locale != null) {
+            return locale;
+        }
+
+        return this.readStoredLocalFromCurrentInvocation(invocation);
+    }
+
+    protected Locale readStoredLocalFromSession(ActionInvocation invocation, 
Map<String, Object> session) {
+         // check session for saved locale
         Object sessionLocale = session.get(attributeName);
         if (sessionLocale != null && sessionLocale instanceof Locale) {
             Locale locale = (Locale) sessionLocale;
@@ -185,37 +255,19 @@ public class I18nInterceptor extends Abs
             }
             return locale;
         }
+        return null;
+    }
 
+    protected Locale readStoredLocalFromCurrentInvocation(ActionInvocation 
invocation) {
         // no overriding locale definition found, stay with current invocation 
(=browser) locale
         Locale locale = invocation.getInvocationContext().getLocale();
         if (locale != null && LOG.isDebugEnabled()) {
             LOG.debug("applied invocation context locale=#0", locale);
         }
-
-        return locale;
-    }
-
-    /**
-     * Creates a Locale object from the request param, which might
-     * be already a Local or a String
-     *
-     * @param requestedLocale the parameter from the request
-     * @return the Locale
-     */
-    protected Locale getLocaleFromParam(Object requestedLocale) {
-        Locale locale = null;
-        if (requestedLocale != null) {
-            locale = (requestedLocale instanceof Locale) ?
-                    (Locale) requestedLocale :
-                    
LocalizedTextUtil.localeFromString(requestedLocale.toString(), null);
-            if (locale != null && LOG.isDebugEnabled()) {
-                LOG.debug("applied request locale=#0", locale);
-            }
-        }
         return locale;
     }
 
-    private Object findLocaleParameter(Map<String, Object> params, String 
parameterName) {
+    protected Object findLocaleParameter(Map<String, Object> params, String 
parameterName) {
         Object requestedLocale = params.remove(parameterName);
         if (requestedLocale != null && requestedLocale.getClass().isArray()
                 && ((Object[]) requestedLocale).length == 1) {


Reply via email to