Support favicon at the default location.
[lgpl/argeo-commons.git] / org.argeo.cms.ui.rap / src / org / argeo / cms / web / CmsWebApp.java
index 03ac353df248ab5952daa0ad559747d477131532..c1bd3ad9893c279b0cb9c4f6b715fc6c95916bb5 100644 (file)
@@ -3,27 +3,34 @@ package org.argeo.cms.web;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.logging.Log;
 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.Application.OperationMode;
 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.Constants;
 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;
        private CmsApp cmsApp;
+       private String cmsAppId;
        private EventAdmin eventAdmin;
 
        private ServiceRegistration<ApplicationConfiguration> rwtAppReg;
@@ -31,31 +38,51 @@ public class CmsWebApp implements ApplicationConfiguration, CmsAppListener {
        private final static String CONTEXT_NAME = "contextName";
        private String contextName;
 
+       private final static String FAVICON_PNG = "favicon.png";
+
        public void init(BundleContext bundleContext, Map<String, String> properties) {
                this.bundleContext = bundleContext;
                contextName = properties.get(CONTEXT_NAME);
-               if (cmsApp != null)
-                       themingUpdated();
-//             registerIfAllThemesAvailable();
+               if (cmsApp != null) {
+                       if (cmsApp.allThemesAvailable())
+                               publishWebApp();
+               }
        }
 
        public void destroy(BundleContext bundleContext, Map<String, String> properties) {
-               if (cmsApp != null)
+               if (cmsApp != null) {
                        cmsApp.removeCmsAppListener(this);
+                       cmsApp = null;
+               }
        }
 
        @Override
        public void configure(Application application) {
+               // TODO make it configurable?
+               // SWT compatibility is required for:
+               // - Browser.execute()
+               // - blocking dialogs
+               application.setOperationMode(OperationMode.SWT_COMPATIBILITY);
                for (String uiName : cmsApp.getUiNames()) {
                        CmsTheme theme = cmsApp.getTheme(uiName);
                        if (theme != null)
                                WebThemeUtils.apply(application, theme);
                }
-//             for (CmsTheme theme : themes.values())
-//                     WebThemeUtils.apply(application, theme);
 
                Map<String, String> properties = new HashMap<>();
                addEntryPoints(application, properties);
+               application.setExceptionHandler(this);
+       }
+
+       @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);
+               }
 
        }
 
@@ -66,53 +93,48 @@ public class CmsWebApp implements ApplicationConfiguration, CmsAppListener {
                        if (theme != null) {
                                properties.put(WebClient.THEME_ID, theme.getThemeId());
                                properties.put(WebClient.HEAD_HTML, theme.getHtmlHeaders());
+                               properties.put(WebClient.BODY_HTML, theme.getBodyHtml());
+                               Set<String> imagePaths = theme.getImagesPaths();
+                               if (imagePaths.contains(FAVICON_PNG)) {
+                                       properties.put(WebClient.FAVICON, FAVICON_PNG);
+                               }
                        } else {
                                properties.put(WebClient.THEME_ID, RWT.DEFAULT_THEME_ID);
-//                             if (themeId != null)
-//                                     log.warn("Theme id " + themeId + " was specified but it was not found, using default RWT theme.");
                        }
-                       application.addEntryPoint("/" + uiName, () -> {
+                       String entryPointName = !uiName.equals("") ? "/" + uiName : "/";
+                       application.addEntryPoint(entryPointName, () -> {
                                CmsWebEntryPoint entryPoint = new CmsWebEntryPoint(this, uiName);
                                entryPoint.setEventAdmin(eventAdmin);
                                return entryPoint;
                        }, properties);
                        if (log.isDebugEnabled())
-                               log.info("Added web entry point /" + (contextName != null ? contextName : "") + "/" + uiName);
+                               log.info("Added web entry point " + (contextName != null ? "/" + contextName : "") + entryPointName);
                }
-               log.debug("Published CMS web app /" + (contextName != null ? contextName : ""));
+//             if (log.isDebugEnabled())
+//                     log.debug("Published CMS web app /" + (contextName != null ? contextName : ""));
        }
 
-//     private void registerIfAllThemesAvailable() {
-//             boolean themeMissing = false;
-//             uiNames: for (String uiName : cmsApp.getUiNames()) {
-//                     String themeId = cmsApp.getThemeId(uiName);
-//                     if (RWT.DEFAULT_THEME_ID.equals(themeId))
-//                             continue uiNames;
-//                     if (!themes.containsKey(themeId)) {
-//                             themeMissing = true;
-//                             break uiNames;
-//                     }
-//             }
-//             if (!themeMissing) {
-//                     Dictionary<String, Object> regProps = LangUtils.dict(CONTEXT_NAME, contextName);
-//                     if (bundleContext != null) {
-//                             rwtAppReg = bundleContext.registerService(ApplicationConfiguration.class, this, regProps);
-//                             log.info("Published CMS web app /" + (contextName != null ? contextName : ""));
-//                     }
-//             }
-//     }
-
        CmsApp getCmsApp() {
                return cmsApp;
        }
 
+       BundleContext getBundleContext() {
+               return bundleContext;
+       }
+
        public void setCmsApp(CmsApp cmsApp, Map<String, String> properties) {
                this.cmsApp = cmsApp;
+               this.cmsAppId = properties.get(Constants.SERVICE_PID);
                this.cmsApp.addCmsAppListener(this);
-//             registerIfAllThemesAvailable();
        }
 
        public void unsetCmsApp(CmsApp cmsApp, Map<String, String> properties) {
+               String cmsAppId = properties.get(Constants.SERVICE_PID);
+               if (!cmsAppId.equals(this.cmsAppId))
+                       return;
+               if (this.cmsApp != null) {
+                       this.cmsApp.removeCmsAppListener(this);
+               }
                if (rwtAppReg != null)
                        rwtAppReg.unregister();
                this.cmsApp = null;
@@ -120,6 +142,11 @@ public class CmsWebApp implements ApplicationConfiguration, CmsAppListener {
 
        @Override
        public void themingUpdated() {
+               if (cmsApp != null && cmsApp.allThemesAvailable())
+                       publishWebApp();
+       }
+
+       protected void publishWebApp() {
                Dictionary<String, Object> regProps = LangUtils.dict(CONTEXT_NAME, contextName);
                if (rwtAppReg != null)
                        rwtAppReg.unregister();