1 package org
.argeo
.cms
.web
;
3 import static org
.eclipse
.rap
.rwt
.internal
.service
.ContextProvider
.getApplicationContext
;
6 import java
.net
.URISyntaxException
;
7 import java
.security
.PrivilegedAction
;
8 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
.CmsEventBus
;
18 import org
.argeo
.api
.cms
.CmsLog
;
19 import org
.argeo
.api
.cms
.CmsSession
;
20 import org
.argeo
.api
.cms
.ux
.CmsImageManager
;
21 import org
.argeo
.api
.cms
.ux
.CmsView
;
22 import org
.argeo
.cms
.CurrentUser
;
23 import org
.argeo
.cms
.LocaleUtils
;
24 import org
.argeo
.cms
.auth
.RemoteAuthCallbackHandler
;
25 import org
.argeo
.cms
.servlet
.ServletHttpRequest
;
26 import org
.argeo
.cms
.servlet
.ServletHttpResponse
;
27 import org
.argeo
.cms
.swt
.AbstractSwtCmsView
;
28 import org
.argeo
.cms
.swt
.CmsSwtUtils
;
29 import org
.argeo
.cms
.swt
.SimpleSwtUxContext
;
30 import org
.argeo
.cms
.swt
.acr
.AcrSwtImageManager
;
31 import org
.argeo
.cms
.swt
.dialogs
.CmsFeedback
;
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
.rap
.rwt
.service
.ServerPushSession
;
40 import org
.eclipse
.swt
.SWT
;
41 import org
.eclipse
.swt
.SWTError
;
42 import org
.eclipse
.swt
.widgets
.Composite
;
43 import org
.eclipse
.swt
.widgets
.Display
;
44 import org
.eclipse
.swt
.widgets
.Shell
;
46 /** The {@link CmsView} for a {@link CmsWebApp}. */
47 @SuppressWarnings("restriction")
48 public class CmsWebEntryPoint
extends AbstractSwtCmsView
implements EntryPoint
, CmsView
, BrowserNavigationListener
{
49 private static final long serialVersionUID
= 7733510691684570402L;
50 private final static CmsLog log
= CmsLog
.getLog(CmsWebEntryPoint
.class);
52 private final CmsWebApp cmsWebApp
;
55 // private final JavaScriptExecutor jsExecutor;
56 private final BrowserNavigation browserNavigation
;
58 /** Experimental OS-like multi windows. */
59 private boolean multipleShells
= false;
61 private ServerPushSession serverPushSession
;
63 public CmsWebEntryPoint(CmsWebApp cmsWebApp
, String uiName
) {
65 assert cmsWebApp
!= null;
66 assert uiName
!= null;
67 this.cmsWebApp
= cmsWebApp
;
68 uid
= UUID
.randomUUID().toString();
73 lc
= new LoginContext(CmsAuth
.LOGIN_CONTEXT_USER
,
74 new RemoteAuthCallbackHandler(new ServletHttpRequest(UiContext
.getHttpRequest()),
75 new ServletHttpResponse(UiContext
.getHttpResponse())));
77 } catch (LoginException e
) {
79 lc
= new LoginContext(CmsAuth
.LOGIN_CONTEXT_ANONYMOUS
,
80 new RemoteAuthCallbackHandler(new ServletHttpRequest(UiContext
.getHttpRequest()),
81 new ServletHttpResponse(UiContext
.getHttpResponse())));
83 } catch (LoginException e1
) {
84 throw new IllegalStateException("Cannot log in as anonymous", e1
);
89 // jsExecutor = RWT.getClient().getService(JavaScriptExecutor.class);
90 browserNavigation
= RWT
.getClient().getService(BrowserNavigation
.class);
91 if (browserNavigation
!= null)
92 browserNavigation
.addBrowserNavigationListener(this);
96 protected void createContents(Composite parent
) {
97 Subject
.doAs(loginContext
.getSubject(), new PrivilegedAction
<Void
>() {
101 uxContext
= new SimpleSwtUxContext();
102 imageManager
= (CmsImageManager
) new AcrSwtImageManager();
103 CmsSession cmsSession
= getCmsSession();
104 if (cmsSession
!= null) {
105 UiContext
.setLocale(cmsSession
.getLocale());
106 LocaleUtils
.setThreadLocale(cmsSession
.getLocale());
108 Locale rwtLocale
= RWT
.getUISession().getLocale();
109 LocaleUtils
.setThreadLocale(rwtLocale
);
111 parent
.setData(CmsApp
.UI_NAME_PROPERTY
, uiName
);
112 display
= parent
.getDisplay();
113 ui
= cmsWebApp
.getCmsApp().initUi(parent
);
114 if (ui
instanceof Composite
)
115 ((Composite
) ui
).setLayoutData(CmsSwtUtils
.fillAll());
116 serverPushSession
= new ServerPushSession();
118 // required in order to doAs to work
119 // TODO check whether it would be worth optimising
120 serverPushSession
.start();
121 // we need ui to be set before refresh so that CmsView can store UI context data
123 cmsWebApp
.getCmsApp().refreshUi(ui
, null);
124 } catch (Exception e
) {
125 throw new IllegalStateException("Cannot create entrypoint contents", e
);
133 public synchronized void logout() {
134 if (loginContext
== null)
135 throw new IllegalArgumentException("Login context should not be null");
137 CurrentUser
.logoutCmsSession(loginContext
.getSubject());
138 loginContext
.logout();
139 LoginContext anonymousLc
= new LoginContext(CmsAuth
.LOGIN_CONTEXT_ANONYMOUS
,
140 new RemoteAuthCallbackHandler(new ServletHttpRequest(UiContext
.getHttpRequest()),
141 new ServletHttpResponse(UiContext
.getHttpResponse())));
143 authChange(anonymousLc
);
144 } catch (LoginException e
) {
145 log
.error("Cannot logout", e
);
150 public synchronized void authChange(LoginContext lc
) {
152 throw new IllegalArgumentException("Login context cannot be null");
153 // logout previous login context
154 if (this.loginContext
!= null)
156 this.loginContext
.logout();
157 } catch (LoginException e1
) {
158 log
.warn("Could not log out: " + e1
);
160 this.loginContext
= lc
;
165 public void exception(final Throwable e
) {
166 if (e
instanceof SWTError
) {
167 SWTError swtError
= (SWTError
) e
;
168 if (swtError
.code
== SWT
.ERROR_FUNCTION_DISPOSED
)
171 display
.syncExec(() -> {
172 // TODO internationalise
173 CmsFeedback
.error("Unexpected exception", e
);
179 protected synchronized void doRefresh() {
181 Subject
.doAs(getSubject(), new PrivilegedAction
<Void
>() {
184 // if (exception != null) {
185 // // TODO internationalise
186 // CmsFeedback.error("Unexpected exception", exception);
190 cmsWebApp
.getCmsApp().refreshUi(ui
, state
);
196 /** Sets the state of the entry point and retrieve the related content. */
197 protected String
setState(String newState
) {
198 cmsWebApp
.getCmsApp().setState(ui
, newState
);
204 public void navigateTo(String state
) {
206 String title
= setState(state
);
209 if (browserNavigation
!= null)
210 browserNavigation
.pushState(state
, title
);
213 public CmsImageManager
getImageManager() {
218 public void navigated(BrowserNavigationEvent event
) {
219 setState(event
.getState());
224 public CmsEventBus
getCmsEventBus() {
225 return cmsWebApp
.getCmsEventBus();
229 public CmsApp
getCmsApp() {
230 return cmsWebApp
.getCmsApp();
234 public void stateChanged(String state
, String title
) {
235 browserNavigation
.pushState(state
, title
);
239 public CmsSession
getCmsSession() {
240 CmsSession cmsSession
= cmsWebApp
.getCmsApp().getCmsContext().getCmsSession(getSubject());
241 if (cmsSession
== null)
242 throw new IllegalStateException("No CMS session available for " + getSubject());
247 public URI
toBackendUri(String url
) {
250 } catch (URISyntaxException e
) {
251 throw new IllegalArgumentException("Cannot convert " + url
, e
);
256 * EntryPoint IMPLEMENTATION
260 public int createUI() {
261 Display display
= new Display();
262 Shell shell
= createShell(display
);
263 shell
.setLayout(CmsSwtUtils
.noSpaceGridLayout());
264 CmsSwtUtils
.registerCmsView(shell
, this);
265 createContents(shell
);
267 // if (shell.getMaximized()) {
273 if (getApplicationContext().getLifeCycleFactory().getLifeCycle() instanceof RWTLifeCycle
) {
274 eventLoop
: while (!shell
.isDisposed()) {
276 Subject
.doAs(loginContext
.getSubject(), new PrivilegedAction
<Void
>() {
279 // TODO rather loop here, until there is an auth change
280 if (!display
.readAndDispatch()) {
281 // TODO update UI last access here
287 } catch (SWTError e
) {
288 SWTError swtError
= (SWTError
) e
;
289 if (swtError
.code
== SWT
.ERROR_FUNCTION_DISPOSED
) {
290 log
.error("Unexpected SWT error in event loop, ignoring it. " + e
.getMessage());
293 log
.error("Unexpected SWT error in event loop, shutting down...", e
);
296 } catch (ThreadDeath e
) {
297 // ThreadDeath is expected when the UI thread terminates
298 throw (ThreadDeath
) e
;
300 log
.error("Unexpected error in event loop, shutting down...", e
);
302 } catch (Throwable e
) {
303 log
.error("Unexpected exception in event loop, ignoring it. " + e
.getMessage());
307 if (serverPushSession
!= null)
308 serverPushSession
.stop();
309 if (!display
.isDisposed())
315 protected Shell
createShell(Display display
) {
317 if (!multipleShells
) {
318 shell
= new Shell(display
, SWT
.NO_TRIM
);
319 shell
.setMaximized(true);
321 shell
= new Shell(display
, SWT
.SHELL_TRIM
);
322 shell
.setSize(800, 600);