]> git.argeo.org Git - lgpl/argeo-commons.git/blob - web/CmsWebEntryPoint.java
Prepare next development cycle
[lgpl/argeo-commons.git] / web / CmsWebEntryPoint.java
1 package org.argeo.cms.web;
2
3 import static org.eclipse.rap.rwt.internal.service.ContextProvider.getApplicationContext;
4
5 import java.security.PrivilegedAction;
6 import java.util.Map;
7 import java.util.UUID;
8
9 import javax.security.auth.Subject;
10 import javax.security.auth.login.LoginContext;
11 import javax.security.auth.login.LoginException;
12
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15 import org.argeo.api.NodeConstants;
16 import org.argeo.cms.auth.CurrentUser;
17 import org.argeo.cms.auth.HttpRequestCallbackHandler;
18 import org.argeo.cms.ui.CmsApp;
19 import org.argeo.cms.ui.CmsImageManager;
20 import org.argeo.cms.ui.CmsView;
21 import org.argeo.cms.ui.UxContext;
22 import org.argeo.cms.ui.dialogs.CmsFeedback;
23 import org.argeo.cms.ui.util.CmsUiUtils;
24 import org.argeo.cms.ui.util.DefaultImageManager;
25 import org.argeo.cms.ui.util.SimpleUxContext;
26 import org.argeo.eclipse.ui.specific.UiContext;
27 import org.eclipse.rap.rwt.RWT;
28 import org.eclipse.rap.rwt.application.EntryPoint;
29 import org.eclipse.rap.rwt.client.service.BrowserNavigation;
30 import org.eclipse.rap.rwt.client.service.BrowserNavigationEvent;
31 import org.eclipse.rap.rwt.client.service.BrowserNavigationListener;
32 import org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle;
33 import org.eclipse.swt.SWT;
34 import org.eclipse.swt.widgets.Composite;
35 import org.eclipse.swt.widgets.Display;
36 import org.eclipse.swt.widgets.Shell;
37 import org.osgi.service.event.Event;
38 import org.osgi.service.event.EventAdmin;
39
40 /** The {@link CmsView} for a {@link CmsWebApp}. */
41 public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationListener {
42 private static final long serialVersionUID = 7733510691684570402L;
43 private final static Log log = LogFactory.getLog(CmsWebEntryPoint.class);
44
45 private EventAdmin eventAdmin;
46
47 private final CmsWebApp cmsWebApp;
48 private final String uiName;
49
50 private LoginContext loginContext;
51 private String state;
52 private Throwable exception;
53 private UxContext uxContext;
54 private CmsImageManager imageManager;
55
56 private Composite ui;
57
58 private String uid;
59
60 // Client services
61 // private final JavaScriptExecutor jsExecutor;
62 private final BrowserNavigation browserNavigation;
63
64 /** Experimental OS-like multi windows. */
65 private boolean multipleShells = false;
66
67 public CmsWebEntryPoint(CmsWebApp cmsWebApp, String uiName) {
68 assert cmsWebApp != null;
69 assert uiName != null;
70 this.cmsWebApp = cmsWebApp;
71 this.uiName = uiName;
72 uid = UUID.randomUUID().toString();
73
74 // Initial login
75 LoginContext lc;
76 try {
77 lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
78 new HttpRequestCallbackHandler(UiContext.getHttpRequest(), UiContext.getHttpResponse()));
79 lc.login();
80 } catch (LoginException e) {
81 try {
82 lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS);
83 lc.login();
84 } catch (LoginException e1) {
85 throw new IllegalStateException("Cannot log in as anonymous", e1);
86 }
87 }
88 authChange(lc);
89
90 // jsExecutor = RWT.getClient().getService(JavaScriptExecutor.class);
91 browserNavigation = RWT.getClient().getService(BrowserNavigation.class);
92 if (browserNavigation != null)
93 browserNavigation.addBrowserNavigationListener(this);
94 }
95
96 protected void createContents(Composite parent) {
97 Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Void>() {
98 @Override
99 public Void run() {
100 try {
101 uxContext = new SimpleUxContext();
102 imageManager = new DefaultImageManager();
103 ui = cmsWebApp.getCmsApp().initUi(parent);
104 ui.setData(CmsApp.UI_NAME_PROPERTY, uiName);
105 ui.setLayoutData(CmsUiUtils.fillAll());
106 } catch (Exception e) {
107 throw new IllegalStateException("Cannot create entrypoint contents", e);
108 }
109 return null;
110 }
111 });
112 }
113
114 protected Subject getSubject() {
115 return loginContext.getSubject();
116 }
117
118 @Override
119 public boolean isAnonymous() {
120 return CurrentUser.isAnonymous(getSubject());
121 }
122
123 @Override
124 public synchronized void logout() {
125 if (loginContext == null)
126 throw new IllegalArgumentException("Login context should not be null");
127 try {
128 CurrentUser.logoutCmsSession(loginContext.getSubject());
129 loginContext.logout();
130 LoginContext anonymousLc = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS);
131 anonymousLc.login();
132 authChange(anonymousLc);
133 } catch (LoginException e) {
134 log.error("Cannot logout", e);
135 }
136 }
137
138 @Override
139 public synchronized void authChange(LoginContext lc) {
140 if (lc == null)
141 throw new IllegalArgumentException("Login context cannot be null");
142 // logout previous login context
143 if (this.loginContext != null)
144 try {
145 this.loginContext.logout();
146 } catch (LoginException e1) {
147 log.warn("Could not log out: " + e1);
148 }
149 this.loginContext = lc;
150 doRefresh();
151 }
152
153 @Override
154 public void exception(final Throwable e) {
155 exception = e;
156 log.error("Unexpected exception in CMS", e);
157 doRefresh();
158 }
159
160 protected synchronized void doRefresh() {
161 if (ui != null)
162 Subject.doAs(getSubject(), new PrivilegedAction<Void>() {
163 @Override
164 public Void run() {
165 if (exception != null) {
166 // TODO internationalise
167 CmsFeedback.show("Unexpected exception", exception);
168 exception = null;
169 // TODO report
170 }
171 cmsWebApp.getCmsApp().refreshUi(ui, state);
172 return null;
173 }
174 });
175 }
176
177 /** Sets the state of the entry point and retrieve the related JCR node. */
178 protected String setState(String newState) {
179 cmsWebApp.getCmsApp().setState(ui, newState);
180 state = newState;
181 return null;
182 }
183
184 @Override
185 public UxContext getUxContext() {
186 return uxContext;
187 }
188
189 @Override
190 public String getUid() {
191 return uid;
192 }
193
194 @Override
195 public void navigateTo(String state) {
196 exception = null;
197 String title = setState(state);
198 doRefresh();
199 if (browserNavigation != null)
200 browserNavigation.pushState(state, title);
201 }
202
203 @Override
204 public CmsImageManager getImageManager() {
205 return imageManager;
206 }
207
208 @Override
209 public void navigated(BrowserNavigationEvent event) {
210 setState(event.getState());
211 doRefresh();
212 }
213
214 @Override
215 public void sendEvent(String topic, Map<String, Object> properties) {
216 if (properties.containsKey(CMS_VIEW_UID_PROPERTY) && !properties.get(CMS_VIEW_UID_PROPERTY).equals(uid))
217 throw new IllegalArgumentException("Property " + CMS_VIEW_UID_PROPERTY + " is set to another CMS view uid ("
218 + properties.get(CMS_VIEW_UID_PROPERTY) + ") then " + uid);
219 properties.put(CMS_VIEW_UID_PROPERTY, uid);
220 eventAdmin.sendEvent(new Event(topic, properties));
221 }
222
223 /*
224 * EntryPoint IMPLEMENTATION
225 */
226
227 @Override
228 public int createUI() {
229 Display display = new Display();
230 Shell shell = createShell(display);
231 shell.setLayout(CmsUiUtils.noSpaceGridLayout());
232 CmsView.registerCmsView(shell, this);
233 createContents(shell);
234 shell.layout();
235 // if (shell.getMaximized()) {
236 // shell.layout();
237 // } else {
238 //// shell.pack();
239 // }
240 shell.open();
241 if (getApplicationContext().getLifeCycleFactory().getLifeCycle() instanceof RWTLifeCycle) {
242 while (!shell.isDisposed()) {
243 if (!display.readAndDispatch()) {
244 display.sleep();
245 }
246 }
247 display.dispose();
248 }
249 return 0;
250 }
251
252 protected Shell createShell(Display display) {
253 Shell shell;
254 if (!multipleShells) {
255 shell = new Shell(display, SWT.NO_TRIM);
256 shell.setMaximized(true);
257 } else {
258 shell = new Shell(display, SWT.SHELL_TRIM);
259 shell.setSize(800, 600);
260 }
261 return shell;
262 }
263
264 public void setEventAdmin(EventAdmin eventAdmin) {
265 this.eventAdmin = eventAdmin;
266 }
267
268 }