Improve CMS UI framework.
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 26 Oct 2020 07:45:59 +0000 (08:45 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 26 Oct 2020 07:45:59 +0000 (08:45 +0100)
org.argeo.api/src/org/argeo/api/NodeUtils.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebApp.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java
org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsFeedback.java
org.argeo.cms/src/org/argeo/cms/Localized.java
org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/dialogs/LightweightDialog.java
org.argeo.jcr/src/org/argeo/jcr/Jcr.java
org.argeo.util/src/org/argeo/util/LangUtils.java

index 926f023dbe771ed43081de532f6f62e1b09f8ab0..9cbf82325c0c2452eb35a1b39ba5b86ca148a61e 100644 (file)
@@ -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.
index 03ac353df248ab5952daa0ad559747d477131532..a4088eedccbb61188b6807ab6c8fcdf8b10cfd22 100644 (file)
@@ -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<String, String> commonProperties) {
                for (String uiName : cmsApp.getUiNames()) {
                        Map<String, String> properties = new HashMap<>(commonProperties);
index 62786f5afa0e477a180db2547792514feda3df62..3d353d6b15ea18f816367ad574a6cbbe9fa5c40c 100644 (file)
@@ -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();
        }
 
index de91bc45cb625b0d909cd4c1a04651d110d62b86..91dc7fb768ac62373814c50a66aa2136ddf6564d 100644 (file)
@@ -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 */
index 1c7c8e5303143bfc93f5dc0117c9ef0b6411ae91..bc37608ed013fd423007412c01a5abbcf71352aa 100644 (file)
@@ -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;
+               }
+
+       }
 }
index c34979e38f1bac0be065a3777bd08e271477e2b3..7c710a45443605f6874988c6b0e29543844bce00 100644 (file)
@@ -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;
index c3db4b604c71b1e8a955b45b2b5019de7a13dd14..0f6059c7f36d09dee42d6c0f85feeb55d622512e 100644 (file)
@@ -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
         */
index 2f99bb3e0d735bb75a99704ce9ffbee2847b560c..1a7a8815e262dd94e5d53becd48370665a36662a 100644 (file)
@@ -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<String, Object> map(String key, Object value) {
+               assert key != null;
+               HashMap<String, Object> props = new HashMap<>();
+               if (value != null)
+                       props.put(key, value);
+               return props;
+       }
+
        /*
         * DICTIONARY
         */