Refactor SWT directory structure.
[lgpl/argeo-commons.git] / swt / rap / org.argeo.cms.swt.rap / src / org / argeo / cms / web / CmsWebApp.java
diff --git a/swt/rap/org.argeo.cms.swt.rap/src/org/argeo/cms/web/CmsWebApp.java b/swt/rap/org.argeo.cms.swt.rap/src/org/argeo/cms/web/CmsWebApp.java
new file mode 100644 (file)
index 0000000..0270933
--- /dev/null
@@ -0,0 +1,167 @@
+package org.argeo.cms.web;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.argeo.api.cms.CmsApp;
+import org.argeo.api.cms.CmsAppListener;
+import org.argeo.api.cms.CmsLog;
+import org.argeo.api.cms.ux.CmsTheme;
+import org.argeo.api.cms.ux.CmsView;
+import org.argeo.cms.swt.CmsSwtUtils;
+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.ServiceRegistration;
+import org.osgi.service.event.EventAdmin;
+
+/** An RWT web app integrating with a {@link CmsApp}. */
+public class CmsWebApp implements ApplicationConfiguration, ExceptionHandler, CmsAppListener {
+       private final static CmsLog log = CmsLog.getLog(CmsWebApp.class);
+
+       private BundleContext bundleContext;
+       private CmsApp cmsApp;
+//     private String cmsAppId;
+       private EventAdmin eventAdmin;
+
+       private ServiceRegistration<ApplicationConfiguration> rwtAppReg;
+
+       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) {
+                       if (cmsApp.allThemesAvailable())
+                               publishWebApp();
+               }
+       }
+
+       public void destroy(BundleContext bundleContext, Map<String, String> properties) {
+               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);
+               }
+
+               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 = CmsSwtUtils.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);
+                       CmsTheme theme = cmsApp.getTheme(uiName);
+                       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);
+                       }
+                       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 : "") + entryPointName);
+               }
+//             if (log.isDebugEnabled())
+//                     log.debug("Published CMS web app /" + (contextName != null ? contextName : ""));
+       }
+
+       CmsApp getCmsApp() {
+               return cmsApp;
+       }
+
+       BundleContext getBundleContext() {
+               return bundleContext;
+       }
+
+       public void setCmsApp(CmsApp cmsApp) {
+               this.cmsApp = cmsApp;
+//             this.cmsAppId = properties.get(Constants.SERVICE_PID);
+               this.cmsApp.addCmsAppListener(this);
+       }
+
+       public void unsetCmsApp(CmsApp cmsApp, Map<String, String> properties) {
+               String contextName = properties.get(CmsApp.CONTEXT_NAME_PROPERTY);
+               if (!contextName.equals(this.contextName))
+                       return;
+               if (this.cmsApp != null) {
+                       this.cmsApp.removeCmsAppListener(this);
+               }
+               if (rwtAppReg != null)
+                       rwtAppReg.unregister();
+               this.cmsApp = null;
+       }
+
+       @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();
+               if (bundleContext != null) {
+                       rwtAppReg = bundleContext.registerService(ApplicationConfiguration.class, this, regProps);
+                       if (log.isDebugEnabled())
+                               log.debug("Publishing CMS web app /" + (contextName != null ? contextName : "") + " ...");
+               }
+       }
+
+       public void setEventAdmin(EventAdmin eventAdmin) {
+               this.eventAdmin = eventAdmin;
+       }
+
+       public void setContextName(String contextName) {
+               this.contextName = contextName;
+       }
+
+}