From b5644c1dac96afe8b9bdcd68068c054a9f780926 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Mon, 26 Oct 2020 08:45:59 +0100 Subject: [PATCH] Improve CMS UI framework. --- .../src/org/argeo/api/NodeUtils.java | 11 +++++++++ .../src/org/argeo/cms/web/CmsWebApp.java | 17 ++++++++++++- .../org/argeo/cms/web/CmsWebEntryPoint.java | 3 ++- .../org/argeo/cms/ui/dialogs/CmsFeedback.java | 10 +++++--- .../src/org/argeo/cms/Localized.java | 14 +++++++++++ .../eclipse/ui/dialogs/LightweightDialog.java | 24 +++++++++++-------- org.argeo.jcr/src/org/argeo/jcr/Jcr.java | 17 ++++++++++++- .../src/org/argeo/util/LangUtils.java | 15 ++++++++++++ 8 files changed, 95 insertions(+), 16 deletions(-) diff --git a/org.argeo.api/src/org/argeo/api/NodeUtils.java b/org.argeo.api/src/org/argeo/api/NodeUtils.java index 926f023db..9cbf82325 100644 --- a/org.argeo.api/src/org/argeo/api/NodeUtils.java +++ b/org.argeo.api/src/org/argeo/api/NodeUtils.java @@ -6,6 +6,7 @@ import java.util.Map; import javax.jcr.NoSuchWorkspaceException; import javax.jcr.Node; +import javax.jcr.Property; import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.RepositoryFactory; @@ -199,6 +200,16 @@ public class NodeUtils { return getUserHome(session, userID); } + /** Whether this node is the home of the user of the underlying session. */ + public static boolean isUserHome(Node node) { + try { + String userID = node.getSession().getUserID(); + return node.hasProperty(Property.JCR_ID) && node.getProperty(Property.JCR_ID).getString().equals(userID); + } catch (RepositoryException e) { + throw new IllegalStateException(e); + } + } + /** * Translate the path to this node into a path containing the name of the * repository and the name of the workspace. diff --git a/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebApp.java b/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebApp.java index 03ac353df..a4088eedc 100644 --- a/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebApp.java +++ b/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebApp.java @@ -9,17 +9,20 @@ import org.apache.commons.logging.LogFactory; import org.argeo.cms.ui.CmsApp; import org.argeo.cms.ui.CmsAppListener; import org.argeo.cms.ui.CmsTheme; +import org.argeo.cms.ui.CmsView; import org.argeo.util.LangUtils; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.application.Application; import org.eclipse.rap.rwt.application.ApplicationConfiguration; +import org.eclipse.rap.rwt.application.ExceptionHandler; import org.eclipse.rap.rwt.client.WebClient; +import org.eclipse.swt.widgets.Display; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import org.osgi.service.event.EventAdmin; /** An RWT web app integrating with a {@link CmsApp}. */ -public class CmsWebApp implements ApplicationConfiguration, CmsAppListener { +public class CmsWebApp implements ApplicationConfiguration, ExceptionHandler, CmsAppListener { private final static Log log = LogFactory.getLog(CmsWebApp.class); private BundleContext bundleContext; @@ -59,6 +62,18 @@ public class CmsWebApp implements ApplicationConfiguration, CmsAppListener { } + @Override + public void handleException(Throwable throwable) { + Display display = Display.getCurrent(); + if (display != null && !display.isDisposed()) { + CmsView cmsView = CmsView.getCmsView(display.getActiveShell()); + cmsView.exception(throwable); + } else { + log.error("Unexpected exception outside an UI thread", throwable); + } + + } + protected void addEntryPoints(Application application, Map commonProperties) { for (String uiName : cmsApp.getUiNames()) { Map properties = new HashMap<>(commonProperties); diff --git a/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java b/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java index 62786f5af..3d353d6b1 100644 --- a/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java +++ b/org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java @@ -158,8 +158,9 @@ public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationL @Override public void exception(final Throwable e) { + CmsFeedback.show("Unexpected exception in CMS", e).block(); exception = e; - log.error("Unexpected exception in CMS", e); +// log.error("Unexpected exception in CMS", e); doRefresh(); } diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsFeedback.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsFeedback.java index de91bc45c..91dc7fb76 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsFeedback.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsFeedback.java @@ -32,7 +32,7 @@ public class CmsFeedback extends LightweightDialog { log.error(message, e); } - public static void show(String message, Throwable e) { + public static CmsFeedback show(String message, Throwable e) { // rethrow ThreaDeath in order to make sure that RAP will properly clean // up the UI thread if (e instanceof ThreadDeath) @@ -42,13 +42,17 @@ public class CmsFeedback extends LightweightDialog { CmsFeedback cmsFeedback = new CmsFeedback(null, message, e); cmsFeedback.setBlockOnOpen(false); cmsFeedback.open(); + return cmsFeedback; } catch (Throwable e1) { log.error("Cannot open error feedback (" + e.getMessage() + "), original error below", e); + return null; } } - public static void show(String message) { - new CmsFeedback(null, message, null).open(); + public static CmsFeedback show(String message) { + CmsFeedback cmsFeedback = new CmsFeedback(null, message, null); + cmsFeedback.open(); + return cmsFeedback; } /** Tries to find a display */ diff --git a/org.argeo.cms/src/org/argeo/cms/Localized.java b/org.argeo.cms/src/org/argeo/cms/Localized.java index 1c7c8e530..bc37608ed 100644 --- a/org.argeo.cms/src/org/argeo/cms/Localized.java +++ b/org.argeo.cms/src/org/argeo/cms/Localized.java @@ -24,4 +24,18 @@ public interface Localized { return LocaleUtils.lead(local(locale).toString(), locale); } + static class Untranslated implements Localized { + private String msg; + + public Untranslated(String msg) { + super(); + this.msg = msg; + } + + @Override + public Object local(Locale locale) { + return msg; + } + + } } diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/dialogs/LightweightDialog.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/dialogs/LightweightDialog.java index c34979e38..7c710a454 100644 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/dialogs/LightweightDialog.java +++ b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/dialogs/LightweightDialog.java @@ -116,22 +116,26 @@ public class LightweightDialog { }); if (block) { - try { - runEventLoop(foregoundShell); - } catch (ThreadDeath t) { - returnCode = CANCEL; - if (log.isTraceEnabled()) - log.error("Thread death, canceling dialog", t); - } catch (Throwable t) { - returnCode = CANCEL; - log.error("Cannot open blocking lightweight dialog", t); - } + block(); } if (returnCode == null) returnCode = OK; return returnCode; } + public void block() { + try { + runEventLoop(foregoundShell); + } catch (ThreadDeath t) { + returnCode = CANCEL; + if (log.isTraceEnabled()) + log.error("Thread death, canceling dialog", t); + } catch (Throwable t) { + returnCode = CANCEL; + log.error("Cannot open blocking lightweight dialog", t); + } + } + private boolean hasChildShells() { if (foregoundShell == null) return false; diff --git a/org.argeo.jcr/src/org/argeo/jcr/Jcr.java b/org.argeo.jcr/src/org/argeo/jcr/Jcr.java index c3db4b604..0f6059c7f 100644 --- a/org.argeo.jcr/src/org/argeo/jcr/Jcr.java +++ b/org.argeo.jcr/src/org/argeo/jcr/Jcr.java @@ -366,8 +366,18 @@ public class Jcr { } } - /** Retrieves the {@link Session} related to this node. */ + /** + * Retrieves the {@link Session} related to this node. + * + * @deprecated Use {@link #getSession(Node)} instead. + */ + @Deprecated public static Session session(Node node) { + return getSession(node); + } + + /** Retrieves the {@link Session} related to this node. */ + public static Session getSession(Node node) { try { return node.getSession(); } catch (RepositoryException e) { @@ -414,6 +424,11 @@ public class Jcr { } } + /** Safely and silently logs out the underlying session. */ + public static void logout(Node node) { + Jcr.logout(session(node)); + } + /* * SECURITY */ diff --git a/org.argeo.util/src/org/argeo/util/LangUtils.java b/org.argeo.util/src/org/argeo/util/LangUtils.java index 2f99bb3e0..1a7a8815e 100644 --- a/org.argeo.util/src/org/argeo/util/LangUtils.java +++ b/org.argeo.util/src/org/argeo/util/LangUtils.java @@ -35,6 +35,21 @@ public class LangUtils { return res; } + /* + * MAP + */ + /** + * Creates a new {@link Dictionary} with one key-value pair. Key should not be + * null, but if the value is null, it returns an empty {@link Dictionary}. + */ + public static Map map(String key, Object value) { + assert key != null; + HashMap props = new HashMap<>(); + if (value != null) + props.put(key, value); + return props; + } + /* * DICTIONARY */ -- 2.30.2