package org.joget.apps.app.web; import java.util.Locale; import java.util.TimeZone; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; import org.displaytag.localization.I18nResourceProvider; import org.displaytag.localization.LocaleResolver; import org.joget.apps.app.service.AppUtil; import org.joget.commons.util.HostManager; import org.joget.commons.util.LogUtil; import org.joget.commons.util.ResourceBundleUtil; import org.joget.commons.util.SetupManager; import org.joget.directory.model.User; import org.joget.directory.model.service.DirectoryManager; import org.joget.workflow.model.service.WorkflowUserManager; import org.springframework.context.i18n.LocaleContext; import org.springframework.context.i18n.TimeZoneAwareLocaleContext; import org.springframework.web.servlet.i18n.SessionLocaleResolver; import static org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME; import static org.springframework.web.servlet.i18n.SessionLocaleResolver.TIME_ZONE_SESSION_ATTRIBUTE_NAME; import org.springframework.web.util.WebUtils; public class LocalLocaleResolver extends SessionLocaleResolver implements LocaleResolver, I18nResourceProvider{ private WorkflowUserManager workflowUserManager; private DirectoryManager directoryManager; private SetupManager setupManager; public static final String UNDEFINED_KEY = "???"; //$NON-NLS-1$ public static final String PARAM_NAME = "_lang"; public static final Locale DEFAULT = new Locale("en", "US"); public static final String DEFAULT_LOCALE_KEY = "defaultLocale"; public static final String DEFAULT_LOCALE_EXPIRY_KEY = "locale_expiry"; public static final String CURRENT_LOCALE_KEY = "currentLocale"; public static final String LOCALE_OF_USER = "LOCALE_OF_USER"; public final static String TIMEZONE_OF_USER = "TIMEZONE_OF_USER"; public final static String SYSTEM_TIMEZONE = "SYSTEM_TIMEZONE"; public final static String SYSTEM_TIMEZONE_EXPIRY_KEY = "SYSTEM_TIMEZONE_EXPIRY_KEY"; public final static Long CACHE_DURATION = 5000L; // 5 seconds @Override public LocaleContext resolveLocaleContext(final HttpServletRequest request) { return new TimeZoneAwareLocaleContext() { @Override public Locale getLocale() { Locale locale = null; if (request != null) { locale = (Locale) WebUtils.getSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME); } if (locale == null) { locale = determineDefaultLocale(request); } return locale; } @Override public TimeZone getTimeZone() { TimeZone timeZone = null; if (request != null) { timeZone = (TimeZone) WebUtils.getSessionAttribute(request, TIME_ZONE_SESSION_ATTRIBUTE_NAME); } if (timeZone == null) { timeZone = determineDefaultTimeZone(request); } return timeZone; } }; } @Override protected TimeZone determineDefaultTimeZone(HttpServletRequest request) { TimeZone timezone = null; if (request != null) { // reset profile and set hostname HostManager.initHost(); timezone = (TimeZone) request.getAttribute(SYSTEM_TIMEZONE); if (timezone == null) { // lookup in session HttpSession session = request.getSession(false); if (session != null) { Long defaultExpiry = (Long)session.getAttribute(SYSTEM_TIMEZONE_EXPIRY_KEY); if (defaultExpiry == null || defaultExpiry.compareTo(System.currentTimeMillis()) < 0) { session.removeAttribute(SYSTEM_TIMEZONE); } else { timezone = (TimeZone) session.getAttribute(SYSTEM_TIMEZONE); request.setAttribute(SYSTEM_TIMEZONE, timezone); } } } HttpSession session = request.getSession(false); if (timezone != null && session != null && !getWorkflowUserManager().getCurrentUsername().equals(session.getAttribute(TIMEZONE_OF_USER))) { timezone = null; } } if (timezone == null) { String gmt = null; try { if (!getWorkflowUserManager().isCurrentUserAnonymous()) { String userGmt = null; User user = getWorkflowUserManager().getCurrentUser(); if (user != null) { userGmt = user.getTimeZone(); } if (userGmt != null && !userGmt.isEmpty()) { gmt = userGmt; } } if (gmt == null) { //get system locale String systemGmt = getSetupManager().getSettingValue("systemTimeZone"); if (systemGmt != null && !systemGmt.isEmpty()) { gmt = systemGmt; } } if (gmt != null && !gmt.isEmpty()) { timezone = getTimeZoneByGMT(gmt); if (timezone != null && request != null) { request.setAttribute(SYSTEM_TIMEZONE, timezone); HttpSession session = request.getSession(false); if (session != null) { Long expiry = System.currentTimeMillis() + CACHE_DURATION; session.setAttribute(SYSTEM_TIMEZONE_EXPIRY_KEY, expiry); session.setAttribute(SYSTEM_TIMEZONE, timezone); } } } } catch (Exception e) { LogUtil.warn(getClass().getName(), "Error setting system timezone from setting, using default timezone"); } } if (timezone == null) { timezone = super.getDefaultTimeZone(); } if (request != null) { HttpSession session = request.getSession(false); if (session != null) { session.setAttribute(TIMEZONE_OF_USER, getWorkflowUserManager().getCurrentUsername()); } } return timezone; } @Override protected Locale determineDefaultLocale(HttpServletRequest request){ Locale locale = null; if (request != null) { // reset profile and set hostname HostManager.initHost(); locale = (Locale) request.getAttribute(DEFAULT_LOCALE_KEY); HttpSession session = request.getSession(false); if (locale == null) { // lookup in session if (session != null) { Long defaultExpiry = (Long)session.getAttribute(DEFAULT_LOCALE_EXPIRY_KEY); if (defaultExpiry == null || defaultExpiry.compareTo(System.currentTimeMillis()) < 0) { session.removeAttribute(DEFAULT_LOCALE_KEY); } else { locale = (Locale) session.getAttribute(DEFAULT_LOCALE_KEY); request.setAttribute(DEFAULT_LOCALE_KEY, locale); } } } if (locale != null && session != null && !getWorkflowUserManager().getCurrentUsername().equals(session.getAttribute(LOCALE_OF_USER))) { locale = null; } } if (locale == null) { String localeCode = null; try { String enableUserLocale = getSetupManager().getSettingValue("enableUserLocale"); if (enableUserLocale != null && enableUserLocale.equalsIgnoreCase("true") && !getWorkflowUserManager().isCurrentUserAnonymous()) { String userLocale = null; User user = getWorkflowUserManager().getCurrentUser(); if (user != null) { userLocale = user.getLocale(); } if (userLocale != null && !userLocale.isEmpty()) { localeCode = userLocale; } } if (localeCode == null) { //get system locale String systemLocale = getSetupManager().getSettingValue("systemLocale"); if (systemLocale != null && !systemLocale.isEmpty()) { localeCode = systemLocale; } } if (localeCode != null && !localeCode.isEmpty()) { String[] temp = localeCode.split("_"); if(temp.length == 1){ locale = new Locale(temp[0]); }else if (temp.length == 2){ locale = new Locale(temp[0], temp[1]); }else if (temp.length == 3){ locale = new Locale(temp[0], temp[1], temp[2]); } Locale.setDefault(DEFAULT); if (request != null) { request.setAttribute(DEFAULT_LOCALE_KEY, locale); HttpSession session = request.getSession(false); if (session != null) { Long expiry = System.currentTimeMillis() + CACHE_DURATION; session.setAttribute(DEFAULT_LOCALE_EXPIRY_KEY, expiry); session.setAttribute(DEFAULT_LOCALE_KEY, locale); } } } } catch (Exception e) { LogUtil.warn(getClass().getName(), "Error setting system locale from setting, using default locale"); } } if (locale == null) { locale = DEFAULT; if (request != null) { request.setAttribute(DEFAULT_LOCALE_KEY, locale); } } if (request != null) { HttpSession session = request.getSession(false); if (session != null) { session.setAttribute(LOCALE_OF_USER, getWorkflowUserManager().getCurrentUsername()); } } return locale; } @Override public Locale resolveLocale(HttpServletRequest request) { Locale locale = null; if (request != null) { locale = (Locale) request.getAttribute(CURRENT_LOCALE_KEY); if (request.getParameter(PARAM_NAME) != null && (locale == null || !request.getParameter(PARAM_NAME).equals(locale.toString()))) { locale = null; String paramValue = request.getParameter(PARAM_NAME); String[] temp = paramValue.split("_"); if (temp.length == 1 && !temp[0].isEmpty()) { locale = new Locale(temp[0]); } else if (temp.length == 2) { locale = new Locale(temp[0], temp[1]); } else if (temp.length == 3) { locale = new Locale(temp[0], temp[1], temp[2]); } if (locale != null) { setLocale(request, null, locale); } else { setLocale(request, null, null); } locale = super.resolveLocale(request); request.setAttribute(CURRENT_LOCALE_KEY, locale); } if (locale == null) { locale = super.resolveLocale(request); request.setAttribute(CURRENT_LOCALE_KEY, locale); } } else { locale = determineDefaultLocale(null); } return locale; } @Override public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale){ super.setLocale(request, response, locale); } public String getResource(String resourceKey, String defaultValue, Tag tag, PageContext pageContext) { return ResourceBundleUtil.getMessage(resourceKey, defaultValue); } protected static TimeZone getTimeZoneByGMT(String gmt) { TimeZone timezone = null; try { if (gmt != null && gmt.trim().length() > 0) { if (gmt.contains(".")) { Double rawoffset = Double.parseDouble(gmt) * 60 * 60 * 1000; String[] tzs = TimeZone.getAvailableIDs(rawoffset.intValue()); if (tzs.length > 0) { timezone = TimeZone.getTimeZone(tzs[0]); } } else { try { if (Integer.parseInt(gmt) > 0) { gmt = "+" + gmt; } timezone = TimeZone.getTimeZone("GMT" + gmt); } catch (NumberFormatException e) { timezone = TimeZone.getTimeZone(gmt); } } } } catch (Exception e) {} return timezone; } public void setWorkflowUserManager(WorkflowUserManager workflowUserManager) { this.workflowUserManager = workflowUserManager; } public void setSetupManager(SetupManager setupManager) { this.setupManager = setupManager; } public void setDirectoryManager(DirectoryManager directoryManager) { this.directoryManager = directoryManager; } public WorkflowUserManager getWorkflowUserManager() { if (workflowUserManager == null) { workflowUserManager = (WorkflowUserManager) AppUtil.getApplicationContext().getBean("workflowUserManager"); } return workflowUserManager; } public DirectoryManager getDirectoryManager() { if (directoryManager == null) { directoryManager = (DirectoryManager) AppUtil.getApplicationContext().getBean("directoryManager"); } return directoryManager; } public SetupManager getSetupManager() { if (setupManager == null) { setupManager = (SetupManager) AppUtil.getApplicationContext().getBean("setupManager"); } return setupManager; } }