]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java
Reintegrate RCP into Commons
[lgpl/argeo-commons.git] / rcp / org.argeo.cms.ui.rcp / src / org / argeo / cms / ui / rcp / CmsRcpApp.java
diff --git a/rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java b/rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java
new file mode 100644 (file)
index 0000000..c2f3d65
--- /dev/null
@@ -0,0 +1,277 @@
+package org.argeo.cms.ui.rcp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.api.NodeConstants;
+import org.argeo.api.cms.CmsApp;
+import org.argeo.api.cms.CmsImageManager;
+import org.argeo.api.cms.CmsSession;
+import org.argeo.api.cms.CmsTheme;
+import org.argeo.api.cms.CmsUi;
+import org.argeo.api.cms.CmsView;
+import org.argeo.api.cms.UxContext;
+import org.argeo.cms.osgi.CmsOsgiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.eclipse.e4.ui.css.core.engine.CSSEngine;
+import org.eclipse.e4.ui.css.core.engine.CSSErrorHandler;
+import org.eclipse.e4.ui.css.swt.engine.CSSSWTEngineImpl;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+
+/** Runs a {@link CmsApp} as an SWT desktop application. */
+@SuppressWarnings("restriction")
+public class CmsRcpApp implements CmsView {
+       private final static Log log = LogFactory.getLog(CmsRcpApp.class);
+
+       private BundleContext bundleContext = FrameworkUtil.getBundle(CmsRcpApp.class).getBundleContext();
+
+       private Display display;
+       private Shell shell;
+       private CmsApp cmsApp;
+       private CmsUiThread uiThread;
+
+       // CMS View
+       private String uid;
+       private LoginContext loginContext;
+
+       private EventAdmin eventAdmin;
+
+       private CSSEngine cssEngine;
+
+       private CmsUi ui;
+       // TODO make it configurable
+       private String uiName = "desktop";
+
+       public CmsRcpApp() {
+               uid = UUID.randomUUID().toString();
+       }
+
+       public void init(Map<String, String> properties) {
+               try {
+                       Thread.sleep(5000);
+               } catch (InterruptedException e) {
+                       // silent
+               }
+               uiThread = new CmsUiThread();
+               uiThread.start();
+
+       }
+
+       public void destroy(Map<String, String> properties) {
+               if (!shell.isDisposed())
+                       shell.dispose();
+               try {
+                       uiThread.join();
+               } catch (InterruptedException e) {
+                       // silent
+               } finally {
+                       uiThread = null;
+               }
+       }
+
+       class CmsUiThread extends Thread {
+
+               public CmsUiThread() {
+                       super("CMS UI");
+               }
+
+               @Override
+               public void run() {
+                       display = new Display();
+                       shell = new Shell(display);
+                       shell.setText("Argeo CMS");
+                       Composite parent = shell;
+                       parent.setLayout(new GridLayout());
+                       CmsSwtUtils.registerCmsView(shell, CmsRcpApp.this);
+
+//                     Subject subject = new Subject();
+//                     CmsLoginShell loginShell = new CmsLoginShell(CmsRcpApp.this);
+//                     loginShell.setSubject(subject);
+                       try {
+                               // try pre-auth
+//                             loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject, loginShell);
+                               loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_SINGLE_USER);
+                               loginContext.login();
+                       } catch (LoginException e) {
+                               throw new IllegalStateException("Could not log in.", e);
+//                             loginShell.createUi();
+//                             loginShell.open();
+//
+//                             while (!loginShell.getShell().isDisposed()) {
+//                                     if (!display.readAndDispatch())
+//                                             display.sleep();
+//                             }
+                       }
+                       if (log.isDebugEnabled())
+                               log.debug("Logged in to desktop: " + loginContext.getSubject());
+
+                       Subject.doAs(loginContext.getSubject(), (PrivilegedAction<Void>) () -> {
+
+                               // TODO factorise with web app
+                               parent.setData(CmsApp.UI_NAME_PROPERTY, uiName);
+                               ui = cmsApp.initUi(parent);
+                               if (ui instanceof Composite)
+                                       ((Composite) ui).setLayoutData(CmsSwtUtils.fillAll());
+                               //ui.setLayoutData(CmsUiUtils.fillAll());
+                               // we need ui to be set before refresh so that CmsView can store UI context data
+                               // in it.
+                               cmsApp.refreshUi(ui, null);
+
+                               // Styling
+                               CmsTheme theme = CmsSwtUtils.getCmsTheme(parent);
+                               if (theme != null) {
+                                       cssEngine = new CSSSWTEngineImpl(display);
+                                       for (String path : theme.getSwtCssPaths()) {
+                                               try (InputStream in = theme.loadPath(path)) {
+                                                       cssEngine.parseStyleSheet(in);
+                                               } catch (IOException e) {
+                                                       throw new IllegalStateException("Cannot load stylesheet " + path, e);
+                                               }
+                                       }
+                                       cssEngine.setErrorHandler(new CSSErrorHandler() {
+                                               public void error(Exception e) {
+                                                       log.error("SWT styling error: ", e);
+                                               }
+                                       });
+                                       applyStyles(shell);
+                               }
+                               shell.layout(true, true);
+
+                               shell.open();
+                               while (!shell.isDisposed()) {
+                                       if (!display.readAndDispatch())
+                                               display.sleep();
+                               }
+                               display.dispose();
+                               return null;
+                       });
+               }
+
+       }
+
+       /*
+        * CMS VIEW
+        */
+
+       @Override
+       public String getUid() {
+               return uid;
+       }
+
+       @Override
+       public UxContext getUxContext() {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public void navigateTo(String state) {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public void authChange(LoginContext loginContext) {
+       }
+
+       @Override
+       public void logout() {
+               if (loginContext != null)
+                       try {
+                               loginContext.logout();
+                       } catch (LoginException e) {
+                               log.error("Cannot log out", e);
+                       }
+       }
+
+       @Override
+       public void exception(Throwable e) {
+               log.error("Unexpected exception in CMS RCP", e);
+       }
+
+       @Override
+       public CmsImageManager getImageManager() {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public CmsSession getCmsSession() {
+               CmsSession cmsSession = CmsOsgiUtils.getCmsSession(bundleContext, getSubject());
+               return cmsSession;
+       }
+
+       @Override
+       public Object getData(String key) {
+               if (ui != null) {
+                       return ui.getData(key);
+               } else {
+                       throw new IllegalStateException("UI is not initialized");
+               }
+       }
+
+       @Override
+       public void setData(String key, Object value) {
+               if (ui != null) {
+                       ui.setData(key, value);
+               } else {
+                       throw new IllegalStateException("UI is not initialized");
+               }
+       }
+
+       @Override
+       public boolean isAnonymous() {
+               return false;
+       }
+
+       @Override
+       public void applyStyles(Object node) {
+               if (cssEngine != null)
+                       cssEngine.applyStyles(node, true);
+       }
+
+       @Override
+       public void sendEvent(String topic, Map<String, Object> properties) {
+               if (properties == null)
+                       properties = new HashMap<>();
+               if (properties.containsKey(CMS_VIEW_UID_PROPERTY) && !properties.get(CMS_VIEW_UID_PROPERTY).equals(uid))
+                       throw new IllegalArgumentException("Property " + CMS_VIEW_UID_PROPERTY + " is set to another CMS view uid ("
+                                       + properties.get(CMS_VIEW_UID_PROPERTY) + ") then " + uid);
+               properties.put(CMS_VIEW_UID_PROPERTY, uid);
+               eventAdmin.sendEvent(new Event(topic, properties));
+       }
+
+       public <T> T doAs(PrivilegedAction<T> action) {
+               return Subject.doAs(getSubject(), action);
+       }
+
+       protected Subject getSubject() {
+               return loginContext.getSubject();
+       }
+
+       /*
+        * DEPENDENCY INJECTION
+        */
+       public void setCmsApp(CmsApp cmsApp) {
+               this.cmsApp = cmsApp;
+       }
+
+       public void setEventAdmin(EventAdmin eventAdmin) {
+               this.eventAdmin = eventAdmin;
+       }
+
+}