]> git.argeo.org Git - lgpl/argeo-commons.git/blob - SimpleApp.java
51aafcb23794d3295b2b846c82ba50e980d1389d
[lgpl/argeo-commons.git] / SimpleApp.java
1 package org.argeo.cms.util;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.HashMap;
8 import java.util.Hashtable;
9 import java.util.LinkedHashMap;
10 import java.util.List;
11 import java.util.Map;
12
13 import javax.jcr.Repository;
14 import javax.jcr.RepositoryException;
15 import javax.jcr.Session;
16 import javax.jcr.security.Privilege;
17 import javax.jcr.version.VersionManager;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.argeo.cms.CmsException;
22 import org.argeo.cms.ui.CmsConstants;
23 import org.argeo.cms.ui.CmsUiProvider;
24 import org.argeo.cms.ui.LifeCycleUiProvider;
25 import org.argeo.jcr.JcrUtils;
26 import org.eclipse.rap.rwt.RWT;
27 import org.eclipse.rap.rwt.application.Application;
28 import org.eclipse.rap.rwt.application.Application.OperationMode;
29 import org.eclipse.rap.rwt.application.ApplicationConfiguration;
30 import org.eclipse.rap.rwt.application.EntryPoint;
31 import org.eclipse.rap.rwt.application.EntryPointFactory;
32 import org.eclipse.rap.rwt.application.ExceptionHandler;
33 import org.eclipse.rap.rwt.client.WebClient;
34 import org.eclipse.rap.rwt.client.service.JavaScriptExecutor;
35 import org.eclipse.rap.rwt.service.ResourceLoader;
36 import org.eclipse.swt.SWT;
37 import org.eclipse.swt.events.SelectionAdapter;
38 import org.eclipse.swt.events.SelectionEvent;
39 import org.eclipse.swt.layout.FillLayout;
40 import org.eclipse.swt.widgets.Button;
41 import org.eclipse.swt.widgets.Composite;
42 import org.osgi.framework.BundleContext;
43 import org.osgi.framework.ServiceRegistration;
44
45 /** A basic generic app based on {@link SimpleErgonomics}. */
46 public class SimpleApp implements CmsConstants, ApplicationConfiguration {
47 private final static Log log = LogFactory.getLog(SimpleApp.class);
48
49 private String contextName = null;
50
51 private Map<String, Map<String, String>> branding = new HashMap<String, Map<String, String>>();
52 private Map<String, List<String>> styleSheets = new HashMap<String, List<String>>();
53
54 private List<String> resources = new ArrayList<String>();
55
56 private BundleContext bundleContext;
57
58 private Repository repository;
59 private String workspace = null;
60 private String jcrBasePath = "/";
61 private List<String> roPrincipals = Arrays.asList("anonymous", "everyone");
62 private List<String> rwPrincipals = Arrays.asList("everyone");
63
64 private CmsUiProvider header;
65 private Map<String, CmsUiProvider> pages = new LinkedHashMap<String, CmsUiProvider>();
66
67 private Integer headerHeight = 40;
68
69 private ServiceRegistration<ApplicationConfiguration> appReg;
70
71 public void configure(Application application) {
72 try {
73 StyleSheetResourceLoader styleSheetRL = new StyleSheetResourceLoader(bundleContext);
74 BundleResourceLoader bundleRL = new BundleResourceLoader(bundleContext);
75
76 application.setOperationMode(OperationMode.SWT_COMPATIBILITY);
77 // application.setOperationMode(OperationMode.JEE_COMPATIBILITY);
78
79 application.setExceptionHandler(new CmsExceptionHandler());
80
81 // loading animated gif
82 application.addResource(LOADING_IMAGE, createResourceLoader(LOADING_IMAGE));
83 // empty image
84 application.addResource(NO_IMAGE, createResourceLoader(NO_IMAGE));
85
86 for (String resource : resources) {
87 application.addResource(resource, bundleRL);
88 if (log.isTraceEnabled())
89 log.trace("Resource " + resource);
90 }
91
92 Map<String, String> defaultBranding = null;
93 if (branding.containsKey("*"))
94 defaultBranding = branding.get("*");
95
96 // entry points
97 for (String page : pages.keySet()) {
98 Map<String, String> properties = defaultBranding != null ? new HashMap<String, String>(defaultBranding)
99 : new HashMap<String, String>();
100 if (branding.containsKey(page)) {
101 properties.putAll(branding.get(page));
102 }
103 // favicon
104 if (properties.containsKey(WebClient.FAVICON)) {
105 String faviconRelPath = properties.get(WebClient.FAVICON);
106 application.addResource(faviconRelPath, new BundleResourceLoader(bundleContext));
107 if (log.isTraceEnabled())
108 log.trace("Favicon " + faviconRelPath);
109
110 }
111
112 // page title
113 if (!properties.containsKey(WebClient.PAGE_TITLE)) {
114 if (page.length() > 0)
115 properties.put(WebClient.PAGE_TITLE, Character.toUpperCase(page.charAt(0)) + page.substring(1));
116 }
117
118 // default body HTML
119 if (!properties.containsKey(WebClient.BODY_HTML))
120 properties.put(WebClient.BODY_HTML, DEFAULT_LOADING_BODY);
121
122 //
123 // ADD ENTRY POINT
124 //
125 application.addEntryPoint("/" + page,
126 new CmsEntryPointFactory(pages.get(page), repository, workspace, properties), properties);
127 log.info("Page /" + page);
128 }
129
130 // stylesheets
131 for (String themeId : styleSheets.keySet()) {
132 List<String> cssLst = styleSheets.get(themeId);
133 if (log.isDebugEnabled())
134 log.debug("Theme " + themeId);
135 for (String css : cssLst) {
136 application.addStyleSheet(themeId, css, styleSheetRL);
137 if (log.isTraceEnabled())
138 log.trace(" CSS " + css);
139 }
140
141 }
142 } catch (RuntimeException e) {
143 // Easier access to initialisation errors
144 log.error("Unexpected exception when configuring RWT application.", e);
145 throw e;
146 }
147 }
148
149 public void init() throws RepositoryException {
150 Session session = null;
151 try {
152 session = JcrUtils.loginOrCreateWorkspace(repository, workspace);
153 VersionManager vm = session.getWorkspace().getVersionManager();
154 if (!vm.isCheckedOut("/"))
155 vm.checkout("/");
156 JcrUtils.mkdirs(session, jcrBasePath);
157 for (String principal : rwPrincipals)
158 JcrUtils.addPrivilege(session, jcrBasePath, principal, Privilege.JCR_WRITE);
159 for (String principal : roPrincipals)
160 JcrUtils.addPrivilege(session, jcrBasePath, principal, Privilege.JCR_READ);
161
162 for (String pageName : pages.keySet()) {
163 try {
164 initPage(session, pages.get(pageName));
165 session.save();
166 } catch (Exception e) {
167 throw new CmsException("Cannot initialize page " + pageName, e);
168 }
169 }
170
171 } finally {
172 JcrUtils.logoutQuietly(session);
173 }
174
175 // publish to OSGi
176 register();
177 }
178
179 protected void initPage(Session adminSession, CmsUiProvider page) throws RepositoryException {
180 if (page instanceof LifeCycleUiProvider)
181 ((LifeCycleUiProvider) page).init(adminSession);
182 }
183
184 public void destroy() {
185 for (String pageName : pages.keySet()) {
186 try {
187 CmsUiProvider page = pages.get(pageName);
188 if (page instanceof LifeCycleUiProvider)
189 ((LifeCycleUiProvider) page).destroy();
190 } catch (Exception e) {
191 log.error("Cannot destroy page " + pageName, e);
192 }
193 }
194 }
195
196 protected void register() {
197 Hashtable<String, String> props = new Hashtable<String, String>();
198 if (contextName != null)
199 props.put("contextName", contextName);
200 appReg = bundleContext.registerService(ApplicationConfiguration.class, this, props);
201 if (log.isDebugEnabled())
202 log.debug("Registered " + (contextName == null ? "/" : contextName));
203 }
204
205 protected void unregister() {
206 appReg.unregister();
207 if (log.isDebugEnabled())
208 log.debug("Unregistered " + (contextName == null ? "/" : contextName));
209 }
210
211 public void setRepository(Repository repository) {
212 this.repository = repository;
213 }
214
215 public void setWorkspace(String workspace) {
216 this.workspace = workspace;
217 }
218
219 public void setHeader(CmsUiProvider header) {
220 this.header = header;
221 }
222
223 public void setPages(Map<String, CmsUiProvider> pages) {
224 this.pages = pages;
225 }
226
227 public void setJcrBasePath(String basePath) {
228 this.jcrBasePath = basePath;
229 }
230
231 public void setRoPrincipals(List<String> roPrincipals) {
232 this.roPrincipals = roPrincipals;
233 }
234
235 public void setRwPrincipals(List<String> rwPrincipals) {
236 this.rwPrincipals = rwPrincipals;
237 }
238
239 public void setHeaderHeight(Integer headerHeight) {
240 this.headerHeight = headerHeight;
241 }
242
243 public void setBranding(Map<String, Map<String, String>> branding) {
244 this.branding = branding;
245 }
246
247 public void setStyleSheets(Map<String, List<String>> styleSheets) {
248 this.styleSheets = styleSheets;
249 }
250
251 public void setBundleContext(BundleContext bundleContext) {
252 this.bundleContext = bundleContext;
253 }
254
255 public void setResources(List<String> resources) {
256 this.resources = resources;
257 }
258
259 public void setContextName(String contextName) {
260 this.contextName = contextName;
261 }
262
263 class CmsExceptionHandler implements ExceptionHandler {
264
265 @Override
266 public void handleException(Throwable throwable) {
267 // TODO be smarter
268 CmsUtils.getCmsView().exception(throwable);
269 }
270
271 }
272
273 private class CmsEntryPointFactory implements EntryPointFactory {
274 private final CmsUiProvider page;
275 private final Repository repository;
276 private final String workspace;
277 private final Map<String, String> properties;
278
279 public CmsEntryPointFactory(CmsUiProvider page, Repository repository, String workspace,
280 Map<String, String> properties) {
281 this.page = page;
282 this.repository = repository;
283 this.workspace = workspace;
284 this.properties = properties;
285 }
286
287 @Override
288 public EntryPoint create() {
289 SimpleErgonomics entryPoint = new SimpleErgonomics(repository, workspace, jcrBasePath, page, properties) {
290 private static final long serialVersionUID = -637940404865527290L;
291
292 @Override
293 protected void createAdminArea(Composite parent) {
294 Composite adminArea = new Composite(parent, SWT.NONE);
295 adminArea.setLayout(new FillLayout());
296 Button refresh = new Button(adminArea, SWT.PUSH);
297 refresh.setText("Reload App");
298 refresh.addSelectionListener(new SelectionAdapter() {
299 private static final long serialVersionUID = -7671999525536351366L;
300
301 @Override
302 public void widgetSelected(SelectionEvent e) {
303 long timeBeforeReload = 1000;
304 RWT.getClient().getService(JavaScriptExecutor.class).execute(
305 "setTimeout(function() { " + "location.reload();" + "}," + timeBeforeReload + ");");
306 reloadApp();
307 }
308 });
309 }
310 };
311 // entryPoint.setState("");
312 entryPoint.setHeader(header);
313 entryPoint.setHeaderHeight(headerHeight);
314 // CmsSession.current.set(entryPoint);
315 return entryPoint;
316 }
317
318 private void reloadApp() {
319 new Thread("Refresh app") {
320 @Override
321 public void run() {
322 unregister();
323 register();
324 }
325 }.start();
326 }
327 }
328
329 private static ResourceLoader createResourceLoader(final String resourceName) {
330 return new ResourceLoader() {
331 public InputStream getResourceAsStream(String resourceName) throws IOException {
332 return getClass().getClassLoader().getResourceAsStream(resourceName);
333 }
334 };
335 }
336
337 // private static ResourceLoader createUrlResourceLoader(final URL url) {
338 // return new ResourceLoader() {
339 // public InputStream getResourceAsStream(String resourceName)
340 // throws IOException {
341 // return url.openStream();
342 // }
343 // };
344 // }
345
346 /*
347 * TEXTS
348 */
349 private static String DEFAULT_LOADING_BODY = "<div"
350 + " style=\"position: absolute; left: 50%; top: 50%; margin: -32px -32px; width: 64px; height:64px\">"
351 + "<img src=\"./rwt-resources/" + LOADING_IMAGE
352 + "\" width=\"32\" height=\"32\" style=\"margin: 16px 16px\"/>" + "</div>";
353 }