/****************************************************************************** * Product: Posterita Ajax UI * * Copyright (C) 2007 Posterita Ltd. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * Posterita Ltd., 3, Draper Avenue, Quatre Bornes, Mauritius * * or via info@posterita.org or http://www.posterita.org/ * *****************************************************************************/ package org.adempiere.webui; import java.lang.ref.WeakReference; import java.util.Enumeration; import java.util.Locale; import java.util.Properties; import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.adempiere.base.sso.ISSOPrincipalService; import org.adempiere.base.sso.SSOUtils; import org.adempiere.util.ServerContext; import org.adempiere.util.ServerContextURLHandler; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.component.DrillCommand; import org.adempiere.webui.component.TokenCommand; import org.adempiere.webui.component.ZoomCommand; import org.adempiere.webui.desktop.DefaultDesktop; import org.adempiere.webui.desktop.FavouriteController; import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.session.SessionContextListener; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.theme.ITheme; import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.util.BrowserToken; import org.adempiere.webui.util.DesktopWatchDog; import org.adempiere.webui.util.UserPreference; import org.compiere.Adempiere; import org.compiere.model.MRole; import org.compiere.model.MSession; import org.compiere.model.MSysConfig; import org.compiere.model.MSystem; import org.compiere.model.MTable; import org.compiere.model.MUser; import org.compiere.model.MUserPreference; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.Language; import org.compiere.util.Msg; import org.compiere.util.Util; import org.zkforge.keylistener.Keylistener; import org.zkoss.web.Attributes; import org.zkoss.web.servlet.Servlets; import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.ui.Desktop; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Page; import org.zkoss.zk.ui.Session; import org.zkoss.zk.ui.WebApp; import org.zkoss.zk.ui.event.ClientInfoEvent; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.sys.DesktopCache; import org.zkoss.zk.ui.sys.SessionCtrl; import org.zkoss.zk.ui.sys.WebAppCtrl; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Style; import org.zkoss.zul.Window; /** * Entry point for iDempiere web client * @author Ashley G Ramdass * @date Feb 25, 2007 * @version $Revision: 0.10 $ * * @author hengsin */ public class AdempiereWebUI extends Window implements EventListener, IWebClient { /** {@link Session} attribute to hold current login user id value */ public static final String CHECK_AD_USER_ID_ATTR = "Check_AD_User_ID"; /** Boolean attribute to indicate the HTTP session of a Desktop have been invalidated */ public static final String DESKTOP_SESSION_INVALIDATED_ATTR = "DesktopSessionInvalidated"; /** * generated serial id */ private static final long serialVersionUID = -6725805283410008847L; /** {@link Desktop} attribute to hold {@link IDesktop} reference */ public static final String APPLICATION_DESKTOP_KEY = "application.desktop"; /** org.zkoss.zk.ui.WebApp.name preference from zk.xml */ public static String APP_NAME = null; /** Match to version at lang-addon.xml */ public static final String UID = "1.0.0"; /** Attribute for widget instance name, use for Selenium test */ public static final String WIDGET_INSTANCE_NAME = "instanceName"; /** login and role selection window */ private WLogin loginDesktop; /** client info from browser */ private ClientInfo clientInfo = new ClientInfo(); /** Language for current session */ private String langSession; /** Current login user's preference */ private UserPreference userPreference; /** User preference DB model */ private MUserPreference userPreferences; /** Global key listener */ private Keylistener keyListener; private static final CLogger logger = CLogger.getCLogger(AdempiereWebUI.class); @Deprecated(forRemoval = true, since = "11") public static final String EXECUTION_CARRYOVER_SESSION_KEY = "execution.carryover"; /** Session attribute to hold {@link ClientInfo} reference */ private static final String CLIENT_INFO = "client.info"; /** the use of event thread have been deprecated, this should always be false **/ private static boolean eventThreadEnabled = false; /** Parameters map from browser URL */ private ConcurrentMap m_URLParameters; /** Login completed event */ private static final String ON_LOGIN_COMPLETED = "onLoginCompleted"; /* SysConfig USE_ESC_FOR_TAB_CLOSING */ private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); /** * default constructor */ public AdempiereWebUI() { this.setVisible(false); userPreference = new UserPreference(); // preserve the original URL parameters as is destroyed later on login m_URLParameters = new ConcurrentHashMap(Executions.getCurrent().getParameterMap()); this.addEventListener(ON_LOGIN_COMPLETED, this); } /** * Handle onCreate event from index.zul, don't call this directly. */ public void onCreate() { //handle ping request String ping = Executions.getCurrent().getHeader("X-PING"); if (!Util.isEmpty(ping, true)) { cleanupForPing(); return; } this.getPage().setTitle(ThemeManager.getBrowserTitle()); Executions.getCurrent().getDesktop().enableServerPush(true); SessionManager.setSessionApplication(this); final Session session = Executions.getCurrent().getDesktop().getSession(); Properties ctx = Env.getCtx(); langSession = Env.getContext(ctx, Env.LANGUAGE); if (session.getAttribute(SessionContextListener.SESSION_CTX) == null || !SessionManager.isUserLoggedIn(ctx)) { loginDesktop = new WLogin(this); loginDesktop.createPart(this.getPage()); loginDesktop.getComponent().getRoot().addEventListener(Events.ON_CLIENT_INFO, this); } else { Clients.showBusy(null); if (session.getAttribute(CLIENT_INFO) != null) { clientInfo = (ClientInfo) session.getAttribute(CLIENT_INFO); } getRoot().addEventListener(Events.ON_CLIENT_INFO, this); //use echo event to make sure server push have been started when loginCompleted is call Events.echoEvent(ON_LOGIN_COMPLETED, this, null); } Executions.getCurrent().getDesktop().addListener(new DrillCommand()); Executions.getCurrent().getDesktop().addListener(new TokenCommand()); Executions.getCurrent().getDesktop().addListener(new ZoomCommand()); eventThreadEnabled = Executions.getCurrent().getDesktop().getWebApp().getConfiguration().isEventThreadEnabled(); } /** * perform clean up for ping request */ private void cleanupForPing() { final Desktop desktop = Executions.getCurrent().getDesktop(); final WebApp wapp = desktop.getWebApp(); final DesktopCache desktopCache = ((WebAppCtrl) wapp).getDesktopCache(desktop.getSession()); final Session session = desktop.getSession(); //clear context, invalidate session Env.getCtx().clear(); Adempiere.getThreadPoolExecutor().schedule(() -> { try { ((SessionCtrl)session).invalidateNow(); } catch (Throwable t) { t.printStackTrace(); } try { if (desktopCache.getDesktopIfAny(desktop.getId()) != null) { desktop.setAttribute(DESKTOP_SESSION_INVALIDATED_ATTR, Boolean.TRUE); desktopCache.removeDesktop(desktop); } } catch (Throwable t) { t.printStackTrace(); } }, 1, TimeUnit.SECONDS); } /** * Handle onOK (enter key) event */ public void onOk() { } /** * Handle onCancel(escape key) event */ public void onCancel() { // do not allow to close tab for Events.ON_CTRL_KEY event if(isUseEscForTabClosing) SessionManager.getAppDesktop().setCloseTabWithShortcut(false); } /* (non-Javadoc) * @see org.adempiere.webui.IWebClient#loginCompleted() */ @Override public void loginCompleted() { if (loginDesktop != null) { loginDesktop.getComponent().getRoot().removeEventListener(Events.ON_CLIENT_INFO, this); loginDesktop.detach(); loginDesktop = null; } Properties ctx = Env.getCtx(); String langLogin = Env.getContext(ctx, Env.LANGUAGE); if (langLogin == null || langLogin.length() <= 0) { langLogin = langSession; Env.setContext(ctx, Env.LANGUAGE, langSession); } MSystem system = MSystem.get(Env.getCtx()); Env.setContext(ctx, Env.SYSTEM_NAME, system.getName()); // Validate language Language language = Language.getLanguage(langLogin); String locale = Env.getContext(ctx, AEnv.LOCALE); if (locale != null && locale.length() > 0 && !language.getLocale().toString().equals(locale)) { String adLanguage = language.getAD_Language(); Language tmp = Language.getLanguage(locale); language = new Language(tmp.getName(), adLanguage, tmp.getLocale(), tmp.isDecimalPoint(), tmp.getDateFormat().toPattern(), tmp.getMediaSize()); } else { Language tmp = language; language = new Language(tmp.getName(), tmp.getAD_Language(), tmp.getLocale(), tmp.isDecimalPoint(), tmp.getDateFormat().toPattern(), tmp.getMediaSize()); } Env.verifyLanguage(ctx, language); Env.setContext(ctx, Env.LANGUAGE, language.getAD_Language()); //Bug StringBuilder calendarMsgScript = new StringBuilder(); String monthMore = Msg.getMsg(ctx,"more"); String dayMore = Msg.getMsg(ctx,"more"); calendarMsgScript.append("function _overrideMsgCal() { msgcal.monthMORE = '+{0} ") .append(monthMore).append("';"); calendarMsgScript.append("msgcal.dayMORE = '+{0} ") .append(dayMore).append("'; }"); AuScript auscript = new AuScript(calendarMsgScript.toString()); Clients.response(auscript); // Create adempiere Session - user id in ctx Session currSess = Executions.getCurrent().getDesktop().getSession(); HttpSession httpSess = (HttpSession) currSess.getNativeSession(); String x_Forward_IP = Executions.getCurrent().getHeader("X-Forwarded-For"); MSession mSession = MSession.get (ctx, x_Forward_IP!=null ? x_Forward_IP : Executions.getCurrent().getRemoteAddr(), Executions.getCurrent().getRemoteHost(), httpSess.getId()); if (clientInfo.userAgent != null) { mSession.setDescription(mSession.getDescription() + "\n" + clientInfo.toString()); mSession.saveEx(); } currSess.setAttribute(CHECK_AD_USER_ID_ATTR, Env.getAD_User_ID(ctx)); //enable full interface, relook into this when doing preference Env.setContext(ctx, Env.SHOW_TRANSLATION, true); Env.setContext(ctx, Env.SHOW_ACCOUNTING, MRole.getDefault().isShowAcct()); // to reload preferences when the user refresh the browser userPreference = loadUserPreference(Env.getAD_User_ID(ctx)); userPreferences = MUserPreference.getUserPreference(Env.getAD_User_ID(ctx), Env.getAD_Client_ID(ctx)); //auto commit user preference userPreferences.fillPreferences(); keyListener = new Keylistener(); keyListener.setPage(this.getPage()); keyListener.setCtrlKeys("@a@c@d@e@f@g@h@l@m@n@o@p@q@r@s@t@w@x@z@#left@#right@#up@#down@#home@#end#enter^u@u@#pgdn@#pgup$#f2^#f2"); keyListener.setAutoBlur(false); //create IDesktop instance IDesktop appDesktop = createDesktop(); appDesktop.setClientInfo(clientInfo); appDesktop.createPart(this.getPage()); this.getPage().getDesktop().setAttribute(APPLICATION_DESKTOP_KEY, new WeakReference(appDesktop)); appDesktop.getComponent().getRoot().addEventListener(Events.ON_CLIENT_INFO, this); //track browser tab per session, 1 browser tab = 1 zk Desktop SessionContextListener.addDesktopId(mSession.getAD_Session_ID(), getPage().getDesktop().getId()); //ensure server push is on if (!this.getPage().getDesktop().isServerPushEnabled()) this.getPage().getDesktop().enableServerPush(true); //update session context currSess.setAttribute(SessionContextListener.SESSION_CTX, ServerContext.getCurrentInstance()); MUser user = MUser.get(ctx); BrowserToken.save(mSession, user); Env.setContext(ctx, Env.UI_CLIENT, "zk"); Env.setContext(ctx, Env.DB_TYPE, DB.getDatabase().getName()); StringBuilder localHttpAddr = new StringBuilder(Executions.getCurrent().getScheme()); localHttpAddr.append("://").append(Executions.getCurrent().getLocalAddr()); int port = Executions.getCurrent().getLocalPort(); if (port > 0 && port != 80) { localHttpAddr.append(":").append(port); } Env.setContext(ctx, Env.LOCAL_HTTP_ADDRESS, localHttpAddr.toString()); Env.setContext(ctx, Env.IS_CAN_APPROVE_OWN_DOC, MRole.getDefault().isCanApproveOwnDoc()); Clients.response(new AuScript("zAu.cmd0.clearBusy()")); //add dynamic style for AD tab StringBuilder cssContent = new StringBuilder(); cssContent.append(".adtab-form-borderlayout .z-south-collapsed:before { "); cssContent.append("content: \""); cssContent.append(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Detail"))); cssContent.append("\"; "); cssContent.append("} "); Style style = new Style(); style.setContent(cssContent.toString()); appendChild(style); //init favorite FavouriteController.getInstance(currSess); processParameters(); } /** * process URL parameters from browser */ private void processParameters() { String action = getPrmString("Action"); if ("Zoom".equalsIgnoreCase(action)) { MTable table = null; int tableID = getPrmInt("AD_Table_ID"); if (tableID == 0) { String tableName = getPrmString("TableName"); if (!Util.isEmpty(tableName)) { table = MTable.get(Env.getCtx(), tableName); if (table != null) { tableID = table.getAD_Table_ID(); } } } else { table = MTable.get(Env.getCtx(), tableID); } if (table != null) { String recordUU = getPrmString("Record_UU"); if (!Util.isEmpty(recordUU)) { AEnv.zoomUU(tableID, recordUU); } else { int recordID = getPrmInt("Record_ID"); if (tableID > 0) { AEnv.zoom(tableID, recordID); } } } } m_URLParameters = null; } /** * @param prm parameter name * @return string value for parameter */ private String getPrmString(String prm) { String retValue = ""; if (m_URLParameters != null) { String[] strs = m_URLParameters.get(prm); if (strs != null && strs.length == 1 && strs[0] != null) retValue = strs[0]; } return retValue; } /** * @param prm parameter name * @return integer value for parameter */ private int getPrmInt(String prm) { int retValue = 0; String str = getPrmString(prm); try { if (!Util.isEmpty(str)) retValue = Integer.parseInt(str); } catch (NumberFormatException e) { // ignore } return retValue; } /** * @return key listener */ @Override public Keylistener getKeylistener() { return keyListener; } /** * Create IDesktop instance. Default is {@link DefaultDesktop} * @return {@link IDesktop} */ private IDesktop createDesktop() { IDesktop appDesktop = null; String className = MSysConfig.getValue(MSysConfig.ZK_DESKTOP_CLASS); if ( className != null && className.trim().length() > 0) { try { Class clazz = this.getClass().getClassLoader().loadClass(className); appDesktop = (IDesktop) clazz.getDeclaredConstructor().newInstance(); } catch (Throwable t) { logger.warning("Failed to instantiate desktop. Class=" + className); } } //fallback to default if (appDesktop == null) appDesktop = new DefaultDesktop(); return appDesktop; } /* (non-Javadoc) * @see org.adempiere.webui.IWebClient#logout() */ @Override public void logout() { final Desktop desktop = Executions.getCurrent().getDesktop(); final WebApp wapp = desktop.getWebApp(); final DesktopCache desktopCache = ((WebAppCtrl) wapp).getDesktopCache(desktop.getSession()); boolean isAdminLogin = false; if (desktop.getSession().getAttribute(ISSOPrincipalService.SSO_ADMIN_LOGIN) != null) isAdminLogin = (boolean)desktop.getSession().getAttribute(ISSOPrincipalService.SSO_ADMIN_LOGIN); final Session session = logout0(); //clear context, invalidate session Env.getCtx().clear(); afterLogout(session); desktop.setAttribute(DESKTOP_SESSION_INVALIDATED_ATTR, Boolean.TRUE); //redirect to login page Executions.sendRedirect(isAdminLogin ? "admin.zul" : "index.zul"); try { desktopCache.removeDesktop(desktop); DesktopWatchDog.removeDesktop(desktop); } catch (Throwable t) { t.printStackTrace(); } } /** * after logout action for Session * @param session */ private void afterLogout(final Session session) { try { ((SessionCtrl)session).onDestroyed(); } catch (Throwable t) { t.printStackTrace(); } ((SessionCtrl)session).invalidateNow(); } /** * Auto logout after user close browser tab without first logging out */ public void logoutAfterTabDestroyed(){ Desktop desktop = Executions.getCurrent().getDesktop(); DesktopWatchDog.removeDesktop(desktop); Session session = logout0(); //clear context, invalidate session Env.getCtx().clear(); SessionCtrl ctrl = (SessionCtrl) session; if (!ctrl.isInvalidated() && session.getNativeSession() != null) afterLogout(session); } /** * Logout current session * @return {@link Session} */ protected Session logout0() { Session session = Executions.getCurrent() != null ? Executions.getCurrent().getDesktop().getSession() : null; if (keyListener != null) { keyListener.detach(); keyListener = null; } //stop background thread IDesktop appDesktop = getAppDeskop(); if (appDesktop != null) appDesktop.logout(); //clear remove all children and root component getChildren().clear(); getPage().removeComponents(); //clear session attributes if (session != null) session.getAttributes().clear(); //logout ad_session AEnv.logout(); return session; } /** * @return IDesktop */ @Override public IDesktop getAppDeskop() { Desktop desktop = Executions.getCurrent() != null ? Executions.getCurrent().getDesktop() : null; IDesktop appDesktop = null; if (desktop != null) { @SuppressWarnings("unchecked") WeakReference ref = (WeakReference) desktop.getAttribute(APPLICATION_DESKTOP_KEY); if (ref != null) { appDesktop = ref.get(); } } return appDesktop; } @Override public void onEvent(Event event) { if (event instanceof ClientInfoEvent) { ClientInfoEvent c = (ClientInfoEvent)event; clientInfo = new ClientInfo(); clientInfo.colorDepth = c.getColorDepth(); clientInfo.screenHeight = c.getScreenHeight(); clientInfo.screenWidth = c.getScreenWidth(); clientInfo.devicePixelRatio = c.getDevicePixelRatio(); clientInfo.desktopHeight = c.getDesktopHeight(); clientInfo.desktopWidth = c.getDesktopWidth(); clientInfo.desktopXOffset = c.getDesktopXOffset(); clientInfo.desktopYOffset = c.getDesktopYOffset(); clientInfo.orientation = c.getOrientation(); clientInfo.timeZone = TimeZone.getTimeZone(c.getZoneId()); String ua = Servlets.getUserAgent((ServletRequest) Executions.getCurrent().getNativeRequest()); clientInfo.userAgent = ua; ua = ua.toLowerCase(); clientInfo.tablet = false; if (Executions.getCurrent().getBrowser("mobile") !=null) { clientInfo.tablet = true; } else if (ua.contains("ipad") || ua.contains("iphone") || ua.contains("android")) { clientInfo.tablet = true; } if (getDesktop() != null && getDesktop().getSession() != null) { getDesktop().getSession().setAttribute(CLIENT_INFO, clientInfo); } else if (Executions.getCurrent() != null){ Executions.getCurrent().getSession().setAttribute(CLIENT_INFO, clientInfo); } Env.setContext(Env.getCtx(), Env.CLIENT_INFO_DESKTOP_WIDTH, clientInfo.desktopWidth); Env.setContext(Env.getCtx(), Env.CLIENT_INFO_DESKTOP_HEIGHT, clientInfo.desktopHeight); Env.setContext(Env.getCtx(), Env.CLIENT_INFO_ORIENTATION, clientInfo.orientation); Env.setContext(Env.getCtx(), Env.CLIENT_INFO_MOBILE, clientInfo.tablet); if (clientInfo.timeZone != null) Env.setContext(Env.getCtx(), Env.CLIENT_INFO_TIME_ZONE, clientInfo.timeZone.getID()); IDesktop appDesktop = getAppDeskop(); if (appDesktop != null) appDesktop.setClientInfo(clientInfo); } else if (event.getName().equals(ON_LOGIN_COMPLETED)) { loginCompleted(); } } /** * handle change role event * @param locale * @param context */ private void onChangeRole(Locale locale, Properties context) { SessionManager.setSessionApplication(this); loginDesktop = new WLogin(this); loginDesktop.createPart(this.getPage()); loginDesktop.changeRole(locale, context); loginDesktop.getComponent().getRoot().addEventListener(Events.ON_CLIENT_INFO, this); } /** * @param userId * @return UserPreference */ @Override public UserPreference loadUserPreference(int userId) { userPreference.loadPreference(userId); return userPreference; } /** * @return UserPrerence */ @Override public UserPreference getUserPreference() { return userPreference; } /** * Should always return false * @return true if event thread is enabled */ public static boolean isEventThreadEnabled() { return eventThreadEnabled; } @Override public void changeRole(MUser user) { //save context for re-login Properties properties = new Properties(); Env.setContext(properties, Env.AD_CLIENT_ID, Env.getAD_Client_ID(Env.getCtx())); Env.setContext(properties, Env.AD_CLIENT_NAME, Env.getContext(Env.getCtx(), Env.AD_CLIENT_NAME)); Env.setContext(properties, Env.AD_ORG_ID, Env.getAD_Org_ID(Env.getCtx())); Env.setContext(properties, Env.AD_USER_ID, user.getAD_User_ID()); Env.setContext(properties, Env.SALESREP_ID, user.getAD_User_ID()); Env.setContext(properties, Env.AD_USER_NAME, Env.getContext(Env.getCtx(), Env.AD_USER_NAME)); Env.setContext(properties, Env.AD_ROLE_ID, Env.getAD_Role_ID(Env.getCtx())); Env.setContext(properties, Env.AD_ROLE_NAME, Env.getContext(Env.getCtx(), Env.AD_ROLE_NAME)); Env.setContext(properties, Env.AD_ROLE_TYPE, Env.getContext(Env.getCtx(), Env.AD_ROLE_TYPE)); Env.setContext(properties, Env.IS_CLIENT_ADMIN, Env.getContext(Env.getCtx(), Env.IS_CLIENT_ADMIN)); Env.setContext(properties, Env.USER_LEVEL, Env.getContext(Env.getCtx(), Env.USER_LEVEL)); Env.setContext(properties, Env.AD_ORG_NAME, Env.getContext(Env.getCtx(), Env.AD_ORG_NAME)); Env.setContext(properties, Env.M_WAREHOUSE_ID, Env.getContext(Env.getCtx(), Env.M_WAREHOUSE_ID)); Env.setContext(properties, UserPreference.LANGUAGE_NAME, Env.getContext(Env.getCtx(), UserPreference.LANGUAGE_NAME)); Env.setContext(properties, Env.LANGUAGE, Env.getContext(Env.getCtx(), Env.LANGUAGE)); Env.setContext(properties, AEnv.LOCALE, Env.getContext(Env.getCtx(), AEnv.LOCALE)); Env.setContext(properties, ITheme.ZK_TOOLBAR_BUTTON_SIZE, Env.getContext(Env.getCtx(), ITheme.ZK_TOOLBAR_BUTTON_SIZE)); Env.setContext(properties, ITheme.USE_CSS_FOR_WINDOW_SIZE, Env.getContext(Env.getCtx(), ITheme.USE_CSS_FOR_WINDOW_SIZE)); Env.setContext(properties, ITheme.USE_FONT_ICON_FOR_IMAGE, Env.getContext(Env.getCtx(), ITheme.USE_FONT_ICON_FOR_IMAGE)); Env.setContext(properties, Env.CLIENT_INFO_DESKTOP_WIDTH, clientInfo.desktopWidth); Env.setContext(properties, Env.CLIENT_INFO_DESKTOP_HEIGHT, clientInfo.desktopHeight); Env.setContext(properties, Env.CLIENT_INFO_ORIENTATION, clientInfo.orientation); Env.setContext(properties, Env.CLIENT_INFO_MOBILE, clientInfo.tablet); Env.setContext(properties, Env.CLIENT_INFO_TIME_ZONE, clientInfo.timeZone.getID()); Env.setContext(properties, Env.MFA_Registration_ID, Env.getContext(Env.getCtx(), Env.MFA_Registration_ID)); Desktop desktop = Executions.getCurrent().getDesktop(); Locale locale = (Locale) desktop.getSession().getAttribute(Attributes.PREFERRED_LOCALE); HttpServletRequest httpRequest = (HttpServletRequest) Executions.getCurrent().getNativeRequest(); Env.setContext(properties, SessionContextListener.SERVLET_SESSION_ID, httpRequest.getSession().getId()); if (Env.getCtx().get(ServerContextURLHandler.SERVER_CONTEXT_URL_HANDLER) != null) properties.put(ServerContextURLHandler.SERVER_CONTEXT_URL_HANDLER, Env.getCtx().get(ServerContextURLHandler.SERVER_CONTEXT_URL_HANDLER)); //desktop cleanup IDesktop appDesktop = getAppDeskop(); HttpSession session = httpRequest.getSession(); if (appDesktop != null) appDesktop.logout(T -> {if (T) asyncChangeRole(session, locale, properties, desktop);}); } /** * change role, asynchronous callback from {@link #changeRole(MUser)} * @param httpSession * @param locale * @param properties * @param desktop */ private void asyncChangeRole(HttpSession httpSession, Locale locale, Properties properties, Desktop desktop) { //stop key listener if (keyListener != null) { keyListener.detach(); keyListener = null; } //remove all children component getChildren().clear(); //remove all root components except this Page page = getPage(); page.removeComponents(); this.setPage(page); //clear session attributes Enumeration attributes = httpSession.getAttributeNames(); while(attributes.hasMoreElements()) { String attribute = attributes.nextElement(); //need to keep zk's session attributes if (attribute.contains("zkoss.") || attribute.startsWith("sso.")) continue; httpSession.removeAttribute(attribute); } httpSession.setAttribute(SSOUtils.ISCHANGEROLE_REQUEST, true); //logout ad_session AEnv.logout(); //show change role window and set new context for env and session onChangeRole(locale, properties); Executions.schedule(desktop, e -> DesktopWatchDog.removeOtherDesktopsInSession(desktop), new Event("onRemoveOtherDesktops")); } @Override public ClientInfo getClientInfo() { return clientInfo; } /** * @return setting for setUpload call */ public static String getUploadSetting() { StringBuilder uploadSetting = new StringBuilder("true,native"); int size = MSysConfig.getIntValue(MSysConfig.ZK_MAX_UPLOAD_SIZE, 0); if (size > 0) { uploadSetting.append(",maxsize=").append(size); } return uploadSetting.toString(); } }