X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=swt%2Forg.argeo.app.swt%2Fsrc%2Forg%2Fargeo%2Fapp%2Fswt%2Fux%2FSwtArgeoApp.java;h=b5ff82d7571f7250fb4610b3467021f7a4b382ba;hb=0652a702f6c9109ccb858f658b5cf14e6f73b815;hp=b092e777727f7d6df0e78591d42e74a90e311939;hpb=b17445e0aed102bddb3c20229a39ecb36bbcf6a5;p=gpl%2Fargeo-suite.git diff --git a/swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SwtArgeoApp.java b/swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SwtArgeoApp.java index b092e77..b5ff82d 100644 --- a/swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SwtArgeoApp.java +++ b/swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SwtArgeoApp.java @@ -2,14 +2,18 @@ package org.argeo.app.swt.ux; import static org.argeo.api.cms.ux.CmsView.CMS_VIEW_UID_PROPERTY; +import java.lang.ref.WeakReference; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; import java.util.TreeMap; import java.util.TreeSet; @@ -36,7 +40,6 @@ import org.argeo.app.ux.AppUi; import org.argeo.app.ux.SuiteUxEvent; import org.argeo.cms.LocaleUtils; import org.argeo.cms.Localized; -import org.argeo.cms.acr.ContentUtils; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.cms.swt.acr.SwtUiProvider; import org.argeo.cms.swt.dialogs.CmsFeedback; @@ -92,7 +95,8 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber // private CmsUserManager cmsUserManager; // TODO make more optimal or via CmsSession/CmsView - private Map managedUis = Collections.synchronizedMap(new HashMap<>()); + private Timer janitorTimer = new Timer(true); + private Map> managedUis = new HashMap<>(); // ACR private ContentRepository contentRepository; @@ -105,9 +109,6 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber getCmsContext().getCmsEventBus().addEventSubscriber(event.topic(), this); } - if (log.isDebugEnabled()) - log.info("Argeo Suite App started"); - if (properties.containsKey(DEFAULT_UI_NAME_PROPERTY)) defaultUiName = LangUtils.get(properties, DEFAULT_UI_NAME_PROPERTY); if (properties.containsKey(DEFAULT_THEME_ID_PROPERTY)) @@ -124,27 +125,56 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber pidPrefix = appPid.substring(0, lastDotIndex); } } else { - // TODO doe it make sense to accept that? + // TODO does it make sense to accept that? appPid = ""; } - Objects.requireNonNull(contentRepository, "Content repository must be provided"); Objects.requireNonNull(appUserState, "App user state must be provided"); -// if (pidPrefix == null) -// throw new IllegalArgumentException("PID prefix must be set."); - -// headerPid = pidPrefix + "header"; -// footerPid = pidPrefix + "footer"; -// leadPanePid = pidPrefix + "leadPane"; -// adminLeadPanePid = pidPrefix + "adminLeadPane"; -// loginScreenPid = pidPrefix + "loginScreen"; + + long janitorPeriod = 60 * 60 * 1000;// 1h + janitorTimer.schedule(new TimerTask() { + + @Override + public void run() { + try { + Iterator> uiRefs = managedUis.values().iterator(); + refs: while (uiRefs.hasNext()) { + WeakReference uiRef = uiRefs.next(); + SwtAppUi ui = uiRef.get(); + if (ui == null) { + if (log.isTraceEnabled()) + log.warn("Unreferenced UI in " + appPid + ", removing it"); + uiRefs.remove(); + continue refs; + } + if (!ui.isDisposed() && !ui.getDisplay().isDisposed()) { + ui.getDisplay().asyncExec(() -> { + ui.disposeIfTimedout(); + }); + ui.getDisplay().wake(); + } + } + if (log.isTraceEnabled()) + log.trace(managedUis.size() + " UIs being managed by app " + appPid); + } catch (Exception e) { + e.printStackTrace(); + } + } + }, janitorPeriod, janitorPeriod); + + if (log.isDebugEnabled()) + log.info("Argeo Suite App " + appPid + " started"); } public void stop(Map properties) { - for (SwtAppUi ui : managedUis.values()) + refs: for (WeakReference uiRef : managedUis.values()) { + SwtAppUi ui = uiRef.get(); + if (ui == null) + continue refs; if (!ui.isDisposed() && !ui.getDisplay().isDisposed()) { ui.getDisplay().syncExec(() -> ui.dispose()); } + } managedUis.clear(); if (log.isDebugEnabled()) log.info("Argeo Suite App stopped"); @@ -171,21 +201,11 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber if (theme != null) CmsSwtUtils.registerCmsTheme(uiParent.getShell(), theme); SwtAppUi argeoSuiteUi = new SwtAppUi(uiParent, SWT.INHERIT_DEFAULT); + // TODO make timeout configurable + argeoSuiteUi.setUiTimeout(12 * 60 * 60 * 1000);// 12 hours String uid = cmsView.getUid(); - managedUis.put(uid, argeoSuiteUi); argeoSuiteUi.addDisposeListener(new CleanUpUi(uid)); -// argeoSuiteUi.addDisposeListener((e) -> { -// managedUis.remove(uid); -// if (log.isDebugEnabled()) -// log.debug("Suite UI " + uid + " has been disposed."); -// }); -// Display.getCurrent().disposeExec(() -> { -// if (managedUis.containsKey(uid)) { -// managedUis.remove(uid); -// if (log.isDebugEnabled()) -// log.debug("Suite UI " + uid + " has been disposed from Display#disposeExec()."); -// } -// }); + managedUis.put(uid, new WeakReference<>(argeoSuiteUi)); return argeoSuiteUi; } @@ -202,6 +222,7 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber try { Content context = null; SwtAppUi ui = (SwtAppUi) cmsUi; + ui.updateLastAccess(); String uiName = Objects.toString(ui.getParent().getData(UI_NAME_PROPERTY), null); if (uiName == null) @@ -249,10 +270,10 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber if (cmsSession == null || cmsView.isAnonymous()) { assert publicBasePath != null; Content userDir = contentSession - .get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + publicBasePath); + .get(Content.ROOT_PATH + CmsConstants.SYS_WORKSPACE + publicBasePath); ui.setUserDir(userDir); } else { - Content userDir = appUserState.getOrCreateSessionDir(contentSession, cmsSession); + Content userDir = appUserState.getOrCreateSessionDir(cmsSession); ui.setUserDir(userDir); // Node userDirNode = jcrContentProvider.doInAdminSession((adminSession) -> { // Node node = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession); @@ -469,7 +490,7 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber } // TODO move it to an internal package? - public static String nodeToState(Content node) { + private static String nodeToState(Content node) { return node.getPath(); } @@ -497,6 +518,7 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber SwtAppUi ui = getRelatedUi(event); if (ui == null) return; + ui.updateLastAccess(); ui.getCmsView().runAs(() -> { try { String appTitle = ""; @@ -600,7 +622,10 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber } private SwtAppUi getRelatedUi(Map eventProperties) { - return managedUis.get(get(eventProperties, CMS_VIEW_UID_PROPERTY)); + WeakReference uiRef = managedUis.get(get(eventProperties, CMS_VIEW_UID_PROPERTY)); + if (uiRef == null) + return null; + return uiRef.get(); } public static String get(Map eventProperties, String key) { @@ -682,14 +707,6 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber } } -// public void setCmsUserManager(CmsUserManager cmsUserManager) { -// this.cmsUserManager = cmsUserManager; -// } - -// protected ContentRepository getContentRepository() { -// return contentRepository; -// } - public void setContentRepository(ContentRepository contentRepository) { this.contentRepository = contentRepository; } @@ -707,7 +724,6 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber final String uid; public CleanUpUi(String uid) { - super(); this.uid = uid; }