1 package org
.argeo
.cms
.web
;
3 import static org
.eclipse
.rap
.rwt
.internal
.service
.ContextProvider
.getApplicationContext
;
5 import java
.security
.PrivilegedAction
;
6 import java
.util
.HashMap
;
7 import java
.util
.Locale
;
11 import javax
.security
.auth
.Subject
;
12 import javax
.security
.auth
.login
.LoginContext
;
13 import javax
.security
.auth
.login
.LoginException
;
15 import org
.argeo
.api
.cms
.CmsApp
;
16 import org
.argeo
.api
.cms
.CmsAuth
;
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
.CmsUi
;
21 import org
.argeo
.api
.cms
.CmsView
;
22 import org
.argeo
.api
.cms
.UxContext
;
23 import org
.argeo
.cms
.LocaleUtils
;
24 import org
.argeo
.cms
.auth
.CurrentUser
;
25 import org
.argeo
.cms
.auth
.RemoteAuthCallbackHandler
;
26 import org
.argeo
.cms
.servlet
.ServletHttpRequest
;
27 import org
.argeo
.cms
.servlet
.ServletHttpResponse
;
28 import org
.argeo
.cms
.swt
.CmsSwtUtils
;
29 import org
.argeo
.cms
.swt
.SimpleSwtUxContext
;
30 import org
.argeo
.cms
.swt
.dialogs
.CmsFeedback
;
31 import org
.argeo
.cms
.ui
.util
.DefaultImageManager
;
32 import org
.argeo
.eclipse
.ui
.specific
.UiContext
;
33 import org
.eclipse
.rap
.rwt
.RWT
;
34 import org
.eclipse
.rap
.rwt
.application
.EntryPoint
;
35 import org
.eclipse
.rap
.rwt
.client
.service
.BrowserNavigation
;
36 import org
.eclipse
.rap
.rwt
.client
.service
.BrowserNavigationEvent
;
37 import org
.eclipse
.rap
.rwt
.client
.service
.BrowserNavigationListener
;
38 import org
.eclipse
.rap
.rwt
.internal
.lifecycle
.RWTLifeCycle
;
39 import org
.eclipse
.swt
.SWT
;
40 import org
.eclipse
.swt
.SWTError
;
41 import org
.eclipse
.swt
.widgets
.Composite
;
42 import org
.eclipse
.swt
.widgets
.Display
;
43 import org
.eclipse
.swt
.widgets
.Shell
;
44 import org
.osgi
.service
.event
.Event
;
45 import org
.osgi
.service
.event
.EventAdmin
;
47 /** The {@link CmsView} for a {@link CmsWebApp}. */
48 @SuppressWarnings("restriction")
49 public class CmsWebEntryPoint
implements EntryPoint
, CmsView
, BrowserNavigationListener
{
50 private static final long serialVersionUID
= 7733510691684570402L;
51 private final static CmsLog log
= CmsLog
.getLog(CmsWebEntryPoint
.class);
53 private EventAdmin eventAdmin
;
55 private final CmsWebApp cmsWebApp
;
56 private final String uiName
;
58 private LoginContext loginContext
;
60 private Throwable exception
;
61 private UxContext uxContext
;
62 private CmsImageManager imageManager
;
64 private Display display
;
70 // private final JavaScriptExecutor jsExecutor;
71 private final BrowserNavigation browserNavigation
;
73 /** Experimental OS-like multi windows. */
74 private boolean multipleShells
= false;
76 public CmsWebEntryPoint(CmsWebApp cmsWebApp
, String uiName
) {
77 assert cmsWebApp
!= null;
78 assert uiName
!= null;
79 this.cmsWebApp
= cmsWebApp
;
81 uid
= UUID
.randomUUID().toString();
86 lc
= new LoginContext(CmsAuth
.LOGIN_CONTEXT_USER
,
87 new RemoteAuthCallbackHandler(new ServletHttpRequest(UiContext
.getHttpRequest()),
88 new ServletHttpResponse(UiContext
.getHttpResponse())));
90 } catch (LoginException e
) {
92 lc
= new LoginContext(CmsAuth
.LOGIN_CONTEXT_ANONYMOUS
,
93 new RemoteAuthCallbackHandler(new ServletHttpRequest(UiContext
.getHttpRequest()),
94 new ServletHttpResponse(UiContext
.getHttpResponse())));
96 } catch (LoginException e1
) {
97 throw new IllegalStateException("Cannot log in as anonymous", e1
);
102 // jsExecutor = RWT.getClient().getService(JavaScriptExecutor.class);
103 browserNavigation
= RWT
.getClient().getService(BrowserNavigation
.class);
104 if (browserNavigation
!= null)
105 browserNavigation
.addBrowserNavigationListener(this);
108 protected void createContents(Composite parent
) {
109 Subject
.doAs(loginContext
.getSubject(), new PrivilegedAction
<Void
>() {
113 uxContext
= new SimpleSwtUxContext();
114 imageManager
= new DefaultImageManager();
115 CmsSession cmsSession
= getCmsSession();
116 if (cmsSession
!= null) {
117 UiContext
.setLocale(cmsSession
.getLocale());
118 LocaleUtils
.setThreadLocale(cmsSession
.getLocale());
120 Locale rwtLocale
= RWT
.getUISession().getLocale();
121 LocaleUtils
.setThreadLocale(rwtLocale
);
123 parent
.setData(CmsApp
.UI_NAME_PROPERTY
, uiName
);
124 display
= parent
.getDisplay();
125 ui
= cmsWebApp
.getCmsApp().initUi(parent
);
126 if (ui
instanceof Composite
)
127 ((Composite
) ui
).setLayoutData(CmsSwtUtils
.fillAll());
128 // we need ui to be set before refresh so that CmsView can store UI context data
130 cmsWebApp
.getCmsApp().refreshUi(ui
, null);
131 } catch (Exception e
) {
132 throw new IllegalStateException("Cannot create entrypoint contents", e
);
139 protected Subject
getSubject() {
140 return loginContext
.getSubject();
143 public <T
> T
doAs(PrivilegedAction
<T
> action
) {
144 return Subject
.doAs(getSubject(), action
);
148 public boolean isAnonymous() {
149 return CurrentUser
.isAnonymous(getSubject());
153 public synchronized void logout() {
154 if (loginContext
== null)
155 throw new IllegalArgumentException("Login context should not be null");
157 CurrentUser
.logoutCmsSession(loginContext
.getSubject());
158 loginContext
.logout();
159 LoginContext anonymousLc
= new LoginContext(CmsAuth
.LOGIN_CONTEXT_ANONYMOUS
,
160 new RemoteAuthCallbackHandler(new ServletHttpRequest(UiContext
.getHttpRequest()),
161 new ServletHttpResponse(UiContext
.getHttpResponse())));
163 authChange(anonymousLc
);
164 } catch (LoginException e
) {
165 log
.error("Cannot logout", e
);
170 public synchronized void authChange(LoginContext lc
) {
172 throw new IllegalArgumentException("Login context cannot be null");
173 // logout previous login context
174 if (this.loginContext
!= null)
176 this.loginContext
.logout();
177 } catch (LoginException e1
) {
178 log
.warn("Could not log out: " + e1
);
180 this.loginContext
= lc
;
185 public void exception(final Throwable e
) {
186 if (e
instanceof SWTError
) {
187 SWTError swtError
= (SWTError
) e
;
188 if (swtError
.code
== SWT
.ERROR_FUNCTION_DISPOSED
)
191 display
.syncExec(() -> {
192 // CmsFeedback.show("Unexpected exception in CMS", e);
194 log
.error("Unexpected exception in CMS", e
);
199 protected synchronized void doRefresh() {
201 Subject
.doAs(getSubject(), new PrivilegedAction
<Void
>() {
204 if (exception
!= null) {
205 // TODO internationalise
206 CmsFeedback
.show("Unexpected exception", exception
);
210 cmsWebApp
.getCmsApp().refreshUi(ui
, state
);
216 /** Sets the state of the entry point and retrieve the related JCR node. */
217 protected String
setState(String newState
) {
218 cmsWebApp
.getCmsApp().setState(ui
, newState
);
224 public UxContext
getUxContext() {
229 public String
getUid() {
234 public void navigateTo(String state
) {
236 String title
= setState(state
);
239 if (browserNavigation
!= null)
240 browserNavigation
.pushState(state
, title
);
243 public CmsImageManager
getImageManager() {
248 public void navigated(BrowserNavigationEvent event
) {
249 setState(event
.getState());
254 public void sendEvent(String topic
, Map
<String
, Object
> properties
) {
255 if (properties
== null)
256 properties
= new HashMap
<>();
257 if (properties
.containsKey(CMS_VIEW_UID_PROPERTY
) && !properties
.get(CMS_VIEW_UID_PROPERTY
).equals(uid
))
258 throw new IllegalArgumentException("Property " + CMS_VIEW_UID_PROPERTY
+ " is set to another CMS view uid ("
259 + properties
.get(CMS_VIEW_UID_PROPERTY
) + ") then " + uid
);
260 properties
.put(CMS_VIEW_UID_PROPERTY
, uid
);
261 eventAdmin
.sendEvent(new Event(topic
, properties
));
265 public void stateChanged(String state
, String title
) {
266 browserNavigation
.pushState(state
, title
);
270 public CmsSession
getCmsSession() {
271 CmsSession cmsSession
= cmsWebApp
.getCmsApp().getCmsContext().getCmsSession(getSubject());
276 public Object
getData(String key
) {
278 return ui
.getData(key
);
280 throw new IllegalStateException("UI is not initialized");
285 public void setData(String key
, Object value
) {
287 ui
.setData(key
, value
);
289 throw new IllegalStateException("UI is not initialized");
294 * EntryPoint IMPLEMENTATION
298 public int createUI() {
299 Display display
= new Display();
300 Shell shell
= createShell(display
);
301 shell
.setLayout(CmsSwtUtils
.noSpaceGridLayout());
302 CmsSwtUtils
.registerCmsView(shell
, this);
303 createContents(shell
);
305 // if (shell.getMaximized()) {
311 if (getApplicationContext().getLifeCycleFactory().getLifeCycle() instanceof RWTLifeCycle
) {
312 eventLoop
: while (!shell
.isDisposed()) {
314 if (!display
.readAndDispatch()) {
317 } catch (Throwable e
) {
318 if (e
instanceof SWTError
) {
319 SWTError swtError
= (SWTError
) e
;
320 if (swtError
.code
== SWT
.ERROR_FUNCTION_DISPOSED
) {
321 log
.error("Unexpected SWT error in event loop, ignoring it. " + e
.getMessage());
324 log
.error("Unexpected SWT error in event loop, shutting down...", e
);
327 } else if (e
instanceof ThreadDeath
) {
328 throw (ThreadDeath
) e
;
329 } else if (e
instanceof Error
) {
330 log
.error("Unexpected error in event loop, shutting down...", e
);
333 log
.error("Unexpected exception in event loop, ignoring it. " + e
.getMessage());
338 if (!display
.isDisposed())
344 protected Shell
createShell(Display display
) {
346 if (!multipleShells
) {
347 shell
= new Shell(display
, SWT
.NO_TRIM
);
348 shell
.setMaximized(true);
350 shell
= new Shell(display
, SWT
.SHELL_TRIM
);
351 shell
.setSize(800, 600);
356 public void setEventAdmin(EventAdmin eventAdmin
) {
357 this.eventAdmin
= eventAdmin
;