1 package org
.argeo
.cms
.ui
.rcp
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
5 import java
.security
.PrivilegedAction
;
6 import java
.util
.HashMap
;
10 import javax
.security
.auth
.Subject
;
11 import javax
.security
.auth
.login
.LoginContext
;
12 import javax
.security
.auth
.login
.LoginException
;
14 import org
.argeo
.api
.cms
.CmsApp
;
15 import org
.argeo
.api
.cms
.CmsAuth
;
16 import org
.argeo
.api
.cms
.CmsContext
;
17 import org
.argeo
.api
.cms
.CmsImageManager
;
18 import org
.argeo
.api
.cms
.CmsLog
;
19 import org
.argeo
.api
.cms
.CmsSession
;
20 import org
.argeo
.api
.cms
.CmsTheme
;
21 import org
.argeo
.api
.cms
.CmsUi
;
22 import org
.argeo
.api
.cms
.CmsView
;
23 import org
.argeo
.api
.cms
.UxContext
;
24 import org
.argeo
.cms
.osgi
.CmsOsgiUtils
;
25 import org
.argeo
.cms
.swt
.CmsSwtUtils
;
26 import org
.eclipse
.e4
.ui
.css
.core
.engine
.CSSEngine
;
27 import org
.eclipse
.e4
.ui
.css
.core
.engine
.CSSErrorHandler
;
28 import org
.eclipse
.e4
.ui
.css
.swt
.engine
.CSSSWTEngineImpl
;
29 import org
.eclipse
.swt
.layout
.GridLayout
;
30 import org
.eclipse
.swt
.widgets
.Composite
;
31 import org
.eclipse
.swt
.widgets
.Display
;
32 import org
.eclipse
.swt
.widgets
.Shell
;
33 import org
.osgi
.framework
.BundleContext
;
34 import org
.osgi
.framework
.FrameworkUtil
;
35 import org
.osgi
.service
.event
.Event
;
36 import org
.osgi
.service
.event
.EventAdmin
;
38 /** Runs a {@link CmsApp} as an SWT desktop application. */
39 @SuppressWarnings("restriction")
40 public class CmsRcpApp
implements CmsView
{
41 private final static CmsLog log
= CmsLog
.getLog(CmsRcpApp
.class);
43 private BundleContext bundleContext
= FrameworkUtil
.getBundle(CmsRcpApp
.class).getBundleContext();
45 private Display display
;
47 private CmsApp cmsApp
;
48 private CmsUiThread uiThread
;
50 private CmsContext cmsContext
;
54 private LoginContext loginContext
;
56 private EventAdmin eventAdmin
;
58 private CSSEngine cssEngine
;
61 // TODO make it configurable
62 private String uiName
= "desktop";
65 uid
= UUID
.randomUUID().toString();
68 public void init(Map
<String
, String
> properties
) {
71 } catch (InterruptedException e
) {
74 uiThread
= new CmsUiThread();
79 public void destroy(Map
<String
, String
> properties
) {
80 if (!shell
.isDisposed())
84 } catch (InterruptedException e
) {
91 class CmsUiThread
extends Thread
{
93 public CmsUiThread() {
99 display
= Display
.getDefault();
100 shell
= new Shell(display
);
101 shell
.setText("Argeo CMS");
102 Composite parent
= shell
;
103 parent
.setLayout(new GridLayout());
104 CmsSwtUtils
.registerCmsView(shell
, CmsRcpApp
.this);
106 // Subject subject = new Subject();
107 // CmsLoginShell loginShell = new CmsLoginShell(CmsRcpApp.this);
108 // loginShell.setSubject(subject);
111 // loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject, loginShell);
112 loginContext
= new LoginContext(CmsAuth
.LOGIN_CONTEXT_SINGLE_USER
);
113 loginContext
.login();
114 } catch (LoginException e
) {
115 throw new IllegalStateException("Could not log in.", e
);
116 // loginShell.createUi();
117 // loginShell.open();
119 // while (!loginShell.getShell().isDisposed()) {
120 // if (!display.readAndDispatch())
124 if (log
.isDebugEnabled())
125 log
.debug("Logged in to desktop: " + loginContext
.getSubject());
127 Subject
.doAs(loginContext
.getSubject(), (PrivilegedAction
<Void
>) () -> {
129 // TODO factorise with web app
130 parent
.setData(CmsApp
.UI_NAME_PROPERTY
, uiName
);
131 ui
= cmsApp
.initUi(parent
);
132 if (ui
instanceof Composite
)
133 ((Composite
) ui
).setLayoutData(CmsSwtUtils
.fillAll());
134 // ui.setLayoutData(CmsUiUtils.fillAll());
135 // we need ui to be set before refresh so that CmsView can store UI context data
137 cmsApp
.refreshUi(ui
, null);
140 CmsTheme theme
= CmsSwtUtils
.getCmsTheme(parent
);
142 cssEngine
= new CSSSWTEngineImpl(display
);
143 for (String path
: theme
.getSwtCssPaths()) {
144 try (InputStream in
= theme
.loadPath(path
)) {
145 cssEngine
.parseStyleSheet(in
);
146 } catch (IOException e
) {
147 throw new IllegalStateException("Cannot load stylesheet " + path
, e
);
150 cssEngine
.setErrorHandler(new CSSErrorHandler() {
151 public void error(Exception e
) {
152 log
.error("SWT styling error: ", e
);
157 shell
.layout(true, true);
160 while (!shell
.isDisposed()) {
161 if (!display
.readAndDispatch())
177 public void setCmsContext(CmsContext cmsContext
) {
178 this.cmsContext
= cmsContext
;
182 public String
getUid() {
187 public UxContext
getUxContext() {
188 throw new UnsupportedOperationException();
192 public void navigateTo(String state
) {
193 throw new UnsupportedOperationException();
197 public void authChange(LoginContext loginContext
) {
201 public void logout() {
202 if (loginContext
!= null)
204 loginContext
.logout();
205 } catch (LoginException e
) {
206 log
.error("Cannot log out", e
);
211 public void exception(Throwable e
) {
212 log
.error("Unexpected exception in CMS RCP", e
);
216 public CmsImageManager
getImageManager() {
217 throw new UnsupportedOperationException();
221 public CmsSession
getCmsSession() {
222 CmsSession cmsSession
= CmsOsgiUtils
.getCmsSession(bundleContext
, getSubject());
227 public Object
getData(String key
) {
229 return ui
.getData(key
);
231 throw new IllegalStateException("UI is not initialized");
236 public void setData(String key
, Object value
) {
238 ui
.setData(key
, value
);
240 throw new IllegalStateException("UI is not initialized");
245 public boolean isAnonymous() {
250 public void applyStyles(Object node
) {
251 if (cssEngine
!= null)
252 cssEngine
.applyStyles(node
, true);
256 public void sendEvent(String topic
, Map
<String
, Object
> properties
) {
257 if (properties
== null)
258 properties
= new HashMap
<>();
259 if (properties
.containsKey(CMS_VIEW_UID_PROPERTY
) && !properties
.get(CMS_VIEW_UID_PROPERTY
).equals(uid
))
260 throw new IllegalArgumentException("Property " + CMS_VIEW_UID_PROPERTY
+ " is set to another CMS view uid ("
261 + properties
.get(CMS_VIEW_UID_PROPERTY
) + ") then " + uid
);
262 properties
.put(CMS_VIEW_UID_PROPERTY
, uid
);
263 eventAdmin
.sendEvent(new Event(topic
, properties
));
266 public <T
> T
doAs(PrivilegedAction
<T
> action
) {
267 return Subject
.doAs(getSubject(), action
);
270 protected Subject
getSubject() {
271 return loginContext
.getSubject();
275 * DEPENDENCY INJECTION
277 public void setCmsApp(CmsApp cmsApp
) {
278 this.cmsApp
= cmsApp
;
281 public void setEventAdmin(EventAdmin eventAdmin
) {
282 this.eventAdmin
= eventAdmin
;