Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
274 changes: 118 additions & 156 deletions core/src/main/java/org/apache/struts2/interceptor/I18nInterceptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,11 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.HttpParameters;
import org.apache.struts2.dispatcher.Parameter;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.util.Collections;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -108,6 +101,10 @@ public void setSupportedLocale(String supportedLocale) {
.collect(Collectors.toSet());
}

protected boolean isLocaleSupported(Locale locale) {
return supportedLocale.isEmpty() || supportedLocale.contains(locale);
}

@Inject
public void setLocaleProviderFactory(LocaleProviderFactory localeProviderFactory) {
this.localeProviderFactory = localeProviderFactory;
Expand Down Expand Up @@ -219,202 +216,167 @@ protected void useLocale(ActionInvocation invocation, Locale locale) {
/**
* Uses to handle reading/storing Locale from/in different locations
*/
protected interface LocaleHandler {
Locale find();
Locale read(ActionInvocation invocation);
Locale store(ActionInvocation invocation, Locale locale);
boolean shouldStore();
@Deprecated(forRemoval = true, since = "7.2.0")
protected interface LocaleHandler extends org.apache.struts2.interceptor.i18n.LocaleHandler {
}

protected class RequestLocaleHandler implements LocaleHandler {
/**
* @deprecated Since 7.2.0, use the top-level handler classes in {@code org.apache.struts2.interceptor.i18n}.
* Scheduled for removal in the next release cycle.
*/
@Deprecated(forRemoval = true, since = "7.2.0")
protected abstract class LocaleHandlerAdapter implements LocaleHandler {

protected ActionInvocation actionInvocation;
protected boolean shouldStore = true;
private final org.apache.struts2.interceptor.i18n.LocaleHandler delegate;

protected RequestLocaleHandler(ActionInvocation invocation) {
actionInvocation = invocation;
protected LocaleHandlerAdapter(org.apache.struts2.interceptor.i18n.LocaleHandler delegate) {
this.delegate = delegate;
}

@Override
public Locale find() {
LOG.debug("Searching locale in request under parameter {}", requestOnlyParameterName);

Parameter requestedLocale = findLocaleParameter(actionInvocation, requestOnlyParameterName);
if (requestedLocale.isDefined()) {
return getLocaleFromParam(requestedLocale.getValue());
}

return null;
return delegate.find();
}

@Override
public Locale store(ActionInvocation invocation, Locale locale) {
return locale;
public Locale read(ActionInvocation invocation) {
return delegate.read(invocation);
}

@Override
public Locale read(ActionInvocation invocation) {
LOG.debug("Searching current Invocation context");
// no overriding locale definition found, stay with current invocation (=browser) locale
Locale locale = invocation.getInvocationContext().getLocale();
if (locale != null) {
LOG.debug("Applied invocation context locale: {}", locale);
}
return locale;
public Locale store(ActionInvocation invocation, Locale locale) {
return delegate.store(invocation, locale);
}

@Override
public boolean shouldStore() {
return shouldStore;
return delegate.shouldStore();
}
}

protected class AcceptLanguageLocaleHandler extends RequestLocaleHandler {

protected AcceptLanguageLocaleHandler(ActionInvocation invocation) {
super(invocation);
}
private org.apache.struts2.interceptor.i18n.RequestLocaleHandler createRequestDelegate(ActionInvocation invocation, String requestOnlyParam) {
return new org.apache.struts2.interceptor.i18n.RequestLocaleHandler(invocation, requestOnlyParam) {
@Override
protected Locale getLocaleFromParam(String requestedLocale) {
return I18nInterceptor.this.getLocaleFromParam(requestedLocale);
}

@Override
@SuppressWarnings("rawtypes")
public Locale find() {
if (!supportedLocale.isEmpty()) {
Enumeration locales = actionInvocation.getInvocationContext().getServletRequest().getLocales();
while (locales.hasMoreElements()) {
Locale locale = (Locale) locales.nextElement();
if (supportedLocale.contains(locale)) {
return locale;
}
}
@Override
protected Parameter findLocaleParameter(ActionInvocation inv, String paramName) {
return I18nInterceptor.this.findLocaleParameter(inv, paramName);
}
return super.find();
}

@Override
protected boolean isLocaleSupported(Locale locale) {
return I18nInterceptor.this.isLocaleSupported(locale);
}
};
}

protected class SessionLocaleHandler extends AcceptLanguageLocaleHandler {

protected SessionLocaleHandler(ActionInvocation invocation) {
super(invocation);
}

@Override
public Locale find() {
Locale requestOnlyLocale = super.find();

if (requestOnlyLocale != null) {
LOG.debug("Found locale under request only param, it won't be stored in session!");
shouldStore = false;
return requestOnlyLocale;
private org.apache.struts2.interceptor.i18n.AcceptLanguageLocaleHandler createAcceptLanguageDelegate(ActionInvocation invocation) {
return new org.apache.struts2.interceptor.i18n.AcceptLanguageLocaleHandler(
invocation, requestOnlyParameterName, supportedLocale
) {
@Override
protected Locale getLocaleFromParam(String requestedLocale) {
return I18nInterceptor.this.getLocaleFromParam(requestedLocale);
}

LOG.debug("Searching locale in request under parameter {}", parameterName);
Parameter requestedLocale = findLocaleParameter(actionInvocation, parameterName);
if (requestedLocale.isDefined()) {
return getLocaleFromParam(requestedLocale.getValue());
@Override
protected Parameter findLocaleParameter(ActionInvocation inv, String paramName) {
return I18nInterceptor.this.findLocaleParameter(inv, paramName);
}

return null;
}

@Override
public Locale store(ActionInvocation invocation, Locale locale) {
Map<String, Object> session = invocation.getInvocationContext().getSession();

if (session != null) {
String sessionId = ServletActionContext.getRequest().getSession().getId();
synchronized (sessionId.intern()) {
session.put(attributeName, locale);
}
@Override
protected boolean isLocaleSupported(Locale locale) {
return I18nInterceptor.this.isLocaleSupported(locale);
}
};
}

return locale;
}

@Override
public Locale read(ActionInvocation invocation) {
Locale locale = null;

LOG.debug("Checks session for saved locale");
HttpSession session = ServletActionContext.getRequest().getSession(false);

if (session != null) {
String sessionId = session.getId();
synchronized (sessionId.intern()) {
Object sessionLocale = invocation.getInvocationContext().getSession().get(attributeName);
if (sessionLocale instanceof Locale) {
locale = (Locale) sessionLocale;
LOG.debug("Applied session locale: {}", locale);
}
}
private org.apache.struts2.interceptor.i18n.SessionLocaleHandler createSessionDelegate(ActionInvocation invocation) {
return new org.apache.struts2.interceptor.i18n.SessionLocaleHandler(
invocation, requestOnlyParameterName, supportedLocale, parameterName, attributeName
) {
@Override
protected Locale getLocaleFromParam(String requestedLocale) {
return I18nInterceptor.this.getLocaleFromParam(requestedLocale);
}

if (locale == null) {
LOG.debug("No Locale defined in session, fetching from current request and it won't be stored in session!");
shouldStore = false;
locale = super.read(invocation);
} else {
LOG.debug("Found stored Locale {} in session, using it!", locale);
@Override
protected Parameter findLocaleParameter(ActionInvocation inv, String paramName) {
return I18nInterceptor.this.findLocaleParameter(inv, paramName);
}

return locale;
}
@Override
protected boolean isLocaleSupported(Locale locale) {
return I18nInterceptor.this.isLocaleSupported(locale);
}
};
}

protected class CookieLocaleHandler extends AcceptLanguageLocaleHandler {
protected CookieLocaleHandler(ActionInvocation invocation) {
super(invocation);
}

@Override
public Locale find() {
Locale requestOnlySessionLocale = super.find();
private org.apache.struts2.interceptor.i18n.CookieLocaleHandler createCookieDelegate(ActionInvocation invocation) {
return new org.apache.struts2.interceptor.i18n.CookieLocaleHandler(
invocation, requestOnlyParameterName, supportedLocale, requestCookieParameterName, attributeName
) {
@Override
protected Locale getLocaleFromParam(String requestedLocale) {
return I18nInterceptor.this.getLocaleFromParam(requestedLocale);
}

if (requestOnlySessionLocale != null) {
shouldStore = false;
return requestOnlySessionLocale;
@Override
protected Parameter findLocaleParameter(ActionInvocation inv, String paramName) {
return I18nInterceptor.this.findLocaleParameter(inv, paramName);
}

LOG.debug("Searching locale in request under parameter {}", requestCookieParameterName);
Parameter requestedLocale = findLocaleParameter(actionInvocation, requestCookieParameterName);
if (requestedLocale.isDefined()) {
return getLocaleFromParam(requestedLocale.getValue());
@Override
protected boolean isLocaleSupported(Locale locale) {
return I18nInterceptor.this.isLocaleSupported(locale);
}
};
}

return null;
/**
* @deprecated Since 7.2.0, use {@link org.apache.struts2.interceptor.i18n.RequestLocaleHandler}.
* Scheduled for removal in the next release cycle.
*/
@Deprecated(forRemoval = true, since = "7.2.0")
protected class RequestLocaleHandler extends LocaleHandlerAdapter {
protected RequestLocaleHandler(ActionInvocation invocation) {
super(createRequestDelegate(invocation, requestOnlyParameterName));
}
}

@Override
public Locale store(ActionInvocation invocation, Locale locale) {
HttpServletResponse response = ServletActionContext.getResponse();

Cookie cookie = new Cookie(attributeName, locale.toString());
cookie.setMaxAge(1209600); // two weeks
response.addCookie(cookie);

return locale;
/**
* @deprecated Since 7.2.0, use {@link org.apache.struts2.interceptor.i18n.AcceptLanguageLocaleHandler}.
* Scheduled for removal in the next release cycle.
*/
@Deprecated(forRemoval = true, since = "7.2.0")
protected class AcceptLanguageLocaleHandler extends LocaleHandlerAdapter {
protected AcceptLanguageLocaleHandler(ActionInvocation invocation) {
super(createAcceptLanguageDelegate(invocation));
}
}

@Override
public Locale read(ActionInvocation invocation) {
Locale locale = null;

Cookie[] cookies = ServletActionContext.getRequest().getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (attributeName.equals(cookie.getName())) {
locale = getLocaleFromParam(cookie.getValue());
}
}
}
/**
* @deprecated Since 7.2.0, use {@link org.apache.struts2.interceptor.i18n.SessionLocaleHandler}.
* Scheduled for removal in the next release cycle.
*/
@Deprecated(forRemoval = true, since = "7.2.0")
protected class SessionLocaleHandler extends LocaleHandlerAdapter {
protected SessionLocaleHandler(ActionInvocation invocation) {
super(createSessionDelegate(invocation));
}
}

if (locale == null) {
LOG.debug("No Locale defined in cookie, fetching from current request and it won't be stored!");
shouldStore = false;
locale = super.read(invocation);
} else {
LOG.debug("Found stored Locale {} in cookie, using it!", locale);
}
return locale;
/**
* @deprecated Since 7.2.0, use {@link org.apache.struts2.interceptor.i18n.CookieLocaleHandler}.
* Scheduled for removal in the next release cycle.
*/
@Deprecated(forRemoval = true, since = "7.2.0")
protected class CookieLocaleHandler extends LocaleHandlerAdapter {
protected CookieLocaleHandler(ActionInvocation invocation) {
super(createCookieDelegate(invocation));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.i18n;

import org.apache.struts2.ActionInvocation;
import org.apache.struts2.dispatcher.Parameter;

import java.util.Locale;

public abstract class AbstractLocaleHandler implements LocaleHandler {

protected final ActionInvocation actionInvocation;
private boolean shouldStore = true;

protected AbstractLocaleHandler(ActionInvocation invocation) {
this.actionInvocation = invocation;
}

@Override
public boolean shouldStore() {
return shouldStore;
}

protected void disableStore() {
this.shouldStore = false;
}

protected abstract Locale getLocaleFromParam(String requestedLocale);

protected abstract Parameter findLocaleParameter(ActionInvocation invocation, String parameterName);

protected abstract boolean isLocaleSupported(Locale locale);
}
Loading
Loading