]> git.argeo.org Git - lgpl/argeo-commons.git/blob - rcp/org.argeo.cms.ui.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java
Adapt to changes in CMS
[lgpl/argeo-commons.git] / rcp / org.argeo.cms.ui.rcp / src / org / argeo / cms / ui / rcp / CmsRcpApp.java
1 package org.argeo.cms.ui.rcp;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.security.PrivilegedAction;
6 import java.util.HashMap;
7 import java.util.Map;
8 import java.util.UUID;
9
10 import javax.security.auth.Subject;
11 import javax.security.auth.login.LoginContext;
12 import javax.security.auth.login.LoginException;
13
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;
37
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);
42
43 private BundleContext bundleContext = FrameworkUtil.getBundle(CmsRcpApp.class).getBundleContext();
44
45 private Display display;
46 private Shell shell;
47 private CmsApp cmsApp;
48 private CmsUiThread uiThread;
49
50 private CmsContext cmsContext;
51
52 // CMS View
53 private String uid;
54 private LoginContext loginContext;
55
56 private EventAdmin eventAdmin;
57
58 private CSSEngine cssEngine;
59
60 private CmsUi ui;
61 // TODO make it configurable
62 private String uiName = "desktop";
63
64 public CmsRcpApp() {
65 uid = UUID.randomUUID().toString();
66 }
67
68 public void init(Map<String, String> properties) {
69 try {
70 Thread.sleep(5000);
71 } catch (InterruptedException e) {
72 // silent
73 }
74 uiThread = new CmsUiThread();
75 uiThread.start();
76
77 }
78
79 public void destroy(Map<String, String> properties) {
80 if (!shell.isDisposed())
81 shell.dispose();
82 try {
83 uiThread.join();
84 } catch (InterruptedException e) {
85 // silent
86 } finally {
87 uiThread = null;
88 }
89 }
90
91 class CmsUiThread extends Thread {
92
93 public CmsUiThread() {
94 super("CMS UI");
95 }
96
97 @Override
98 public void run() {
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);
105
106 // Subject subject = new Subject();
107 // CmsLoginShell loginShell = new CmsLoginShell(CmsRcpApp.this);
108 // loginShell.setSubject(subject);
109 try {
110 // try pre-auth
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();
118 //
119 // while (!loginShell.getShell().isDisposed()) {
120 // if (!display.readAndDispatch())
121 // display.sleep();
122 // }
123 }
124 if (log.isDebugEnabled())
125 log.debug("Logged in to desktop: " + loginContext.getSubject());
126
127 Subject.doAs(loginContext.getSubject(), (PrivilegedAction<Void>) () -> {
128
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
136 // in it.
137 cmsApp.refreshUi(ui, null);
138
139 // Styling
140 CmsTheme theme = CmsSwtUtils.getCmsTheme(parent);
141 if (theme != null) {
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);
148 }
149 }
150 cssEngine.setErrorHandler(new CSSErrorHandler() {
151 public void error(Exception e) {
152 log.error("SWT styling error: ", e);
153 }
154 });
155 applyStyles(shell);
156 }
157 shell.layout(true, true);
158
159 shell.open();
160 while (!shell.isDisposed()) {
161 if (!display.readAndDispatch())
162 display.sleep();
163 }
164 display.dispose();
165 return null;
166 });
167 }
168
169 }
170
171
172
173 /*
174 * CMS VIEW
175 */
176
177 public void setCmsContext(CmsContext cmsContext) {
178 this.cmsContext = cmsContext;
179 }
180
181 @Override
182 public String getUid() {
183 return uid;
184 }
185
186 @Override
187 public UxContext getUxContext() {
188 throw new UnsupportedOperationException();
189 }
190
191 @Override
192 public void navigateTo(String state) {
193 throw new UnsupportedOperationException();
194 }
195
196 @Override
197 public void authChange(LoginContext loginContext) {
198 }
199
200 @Override
201 public void logout() {
202 if (loginContext != null)
203 try {
204 loginContext.logout();
205 } catch (LoginException e) {
206 log.error("Cannot log out", e);
207 }
208 }
209
210 @Override
211 public void exception(Throwable e) {
212 log.error("Unexpected exception in CMS RCP", e);
213 }
214
215 @Override
216 public CmsImageManager getImageManager() {
217 throw new UnsupportedOperationException();
218 }
219
220 @Override
221 public CmsSession getCmsSession() {
222 CmsSession cmsSession = CmsOsgiUtils.getCmsSession(bundleContext, getSubject());
223 return cmsSession;
224 }
225
226 @Override
227 public Object getData(String key) {
228 if (ui != null) {
229 return ui.getData(key);
230 } else {
231 throw new IllegalStateException("UI is not initialized");
232 }
233 }
234
235 @Override
236 public void setData(String key, Object value) {
237 if (ui != null) {
238 ui.setData(key, value);
239 } else {
240 throw new IllegalStateException("UI is not initialized");
241 }
242 }
243
244 @Override
245 public boolean isAnonymous() {
246 return false;
247 }
248
249 @Override
250 public void applyStyles(Object node) {
251 if (cssEngine != null)
252 cssEngine.applyStyles(node, true);
253 }
254
255 @Override
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));
264 }
265
266 public <T> T doAs(PrivilegedAction<T> action) {
267 return Subject.doAs(getSubject(), action);
268 }
269
270 protected Subject getSubject() {
271 return loginContext.getSubject();
272 }
273
274 /*
275 * DEPENDENCY INJECTION
276 */
277 public void setCmsApp(CmsApp cmsApp) {
278 this.cmsApp = cmsApp;
279 }
280
281 public void setEventAdmin(EventAdmin eventAdmin) {
282 this.eventAdmin = eventAdmin;
283 }
284
285 }