]> git.argeo.org Git - lgpl/argeo-commons.git/blob - rap/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptApp.java
Introduce static CMS.
[lgpl/argeo-commons.git] / rap / org.argeo.cms.ui.rap / src / org / argeo / cms / ui / script / CmsScriptApp.java
1 package org.argeo.cms.ui.script;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.net.URL;
6 import java.util.ArrayList;
7 import java.util.Enumeration;
8 import java.util.HashMap;
9 import java.util.Hashtable;
10 import java.util.List;
11 import java.util.Map;
12
13 import javax.jcr.Node;
14 import javax.jcr.Property;
15 import javax.jcr.PropertyIterator;
16 import javax.jcr.PropertyType;
17 import javax.jcr.Repository;
18 import javax.jcr.RepositoryException;
19 import javax.script.ScriptEngine;
20 import javax.servlet.http.HttpServletRequest;
21 import javax.servlet.http.HttpServletResponse;
22
23 import org.argeo.api.cms.CmsTheme;
24 import org.argeo.api.cms.CmsLog;
25 import org.argeo.cms.CmsException;
26 import org.argeo.cms.ui.CmsUiConstants;
27 import org.argeo.cms.ui.CmsUiProvider;
28 import org.argeo.cms.ui.util.CmsUiUtils;
29 import org.argeo.cms.web.BundleResourceLoader;
30 import org.argeo.cms.web.SimpleErgonomics;
31 import org.argeo.cms.web.WebThemeUtils;
32 import org.eclipse.rap.rwt.application.Application;
33 import org.eclipse.rap.rwt.application.Application.OperationMode;
34 import org.eclipse.rap.rwt.application.ApplicationConfiguration;
35 import org.eclipse.rap.rwt.application.ExceptionHandler;
36 import org.eclipse.rap.rwt.client.WebClient;
37 import org.eclipse.rap.rwt.service.ResourceLoader;
38 import org.osgi.framework.Bundle;
39 import org.osgi.framework.BundleContext;
40 import org.osgi.framework.ServiceRegistration;
41 import org.osgi.service.http.HttpContext;
42 import org.osgi.service.http.HttpService;
43 import org.osgi.service.http.NamespaceException;
44
45 public class CmsScriptApp implements Branding {
46 public final static String CONTEXT_NAME = "contextName";
47
48 ServiceRegistration<ApplicationConfiguration> appConfigReg;
49
50 private ScriptEngine scriptEngine;
51
52 private final static CmsLog log = CmsLog.getLog(CmsScriptApp.class);
53
54 private String webPath;
55 private String repo = "(cn=node)";
56
57 // private Branding branding = new Branding();
58 private CmsTheme theme;
59
60 private List<String> resources = new ArrayList<>();
61
62 private Map<String, AppUi> ui = new HashMap<>();
63
64 private CmsUiProvider header;
65 private Integer headerHeight = null;
66 private CmsUiProvider lead;
67 private CmsUiProvider end;
68 private CmsUiProvider footer;
69
70 // Branding
71 private String themeId;
72 private String additionalHeaders;
73 private String bodyHtml;
74 private String pageTitle;
75 private String pageOverflow;
76 private String favicon;
77
78 public CmsScriptApp(ScriptEngine scriptEngine) {
79 super();
80 this.scriptEngine = scriptEngine;
81 }
82
83 public void apply(BundleContext bundleContext, Repository repository, Application application) {
84 BundleResourceLoader bundleRL = new BundleResourceLoader(bundleContext.getBundle());
85
86 application.setOperationMode(OperationMode.SWT_COMPATIBILITY);
87 // application.setOperationMode(OperationMode.JEE_COMPATIBILITY);
88
89 application.setExceptionHandler(new CmsExceptionHandler());
90
91 // loading animated gif
92 application.addResource(CmsUiConstants.LOADING_IMAGE, createResourceLoader(CmsUiConstants.LOADING_IMAGE));
93 // empty image
94 application.addResource(CmsUiConstants.NO_IMAGE, createResourceLoader(CmsUiConstants.NO_IMAGE));
95
96 for (String resource : resources) {
97 application.addResource(resource, bundleRL);
98 if (log.isTraceEnabled())
99 log.trace("Resource " + resource);
100 }
101
102 if (theme != null) {
103 WebThemeUtils.apply(application, theme);
104 String themeHeaders = theme.getHtmlHeaders();
105 if (themeHeaders != null) {
106 if (additionalHeaders == null)
107 additionalHeaders = themeHeaders;
108 else
109 additionalHeaders = themeHeaders + "\n" + additionalHeaders;
110 }
111 themeId = theme.getThemeId();
112 }
113
114 // client JavaScript
115 Bundle appBundle = bundleRL.getBundle();
116 BundleContext bc = appBundle.getBundleContext();
117 HttpService httpService = bc.getService(bc.getServiceReference(HttpService.class));
118 HttpContext httpContext = new BundleHttpContext(bc);
119 Enumeration<URL> themeResources = appBundle.findEntries("/js/", "*", true);
120 if (themeResources != null)
121 bundleResources: while (themeResources.hasMoreElements()) {
122 try {
123 String name = themeResources.nextElement().getPath();
124 if (name.endsWith("/"))
125 continue bundleResources;
126 String alias = "/" + getWebPath() + name;
127
128 httpService.registerResources(alias, name, httpContext);
129 if (log.isDebugEnabled())
130 log.debug("Mapped " + name + " to alias " + alias);
131
132 } catch (NamespaceException e) {
133 // TODO Auto-generated catch block
134 e.printStackTrace();
135 }
136 }
137
138 // App UIs
139 for (String appUiName : ui.keySet()) {
140 AppUi appUi = ui.get(appUiName);
141 appUi.apply(repository, application, this, appUiName);
142
143 }
144
145 }
146
147 public void applySides(SimpleErgonomics simpleErgonomics) {
148 simpleErgonomics.setHeader(header);
149 simpleErgonomics.setLead(lead);
150 simpleErgonomics.setEnd(end);
151 simpleErgonomics.setFooter(footer);
152 }
153
154 public void register(BundleContext bundleContext, ApplicationConfiguration appConfig) {
155 Hashtable<String, String> props = new Hashtable<>();
156 props.put(CONTEXT_NAME, webPath);
157 appConfigReg = bundleContext.registerService(ApplicationConfiguration.class, appConfig, props);
158 }
159
160 public void reload() {
161 BundleContext bundleContext = appConfigReg.getReference().getBundle().getBundleContext();
162 ApplicationConfiguration appConfig = bundleContext.getService(appConfigReg.getReference());
163 appConfigReg.unregister();
164 register(bundleContext, appConfig);
165
166 // BundleContext bundleContext = (BundleContext)
167 // getScriptEngine().get("bundleContext");
168 // try {
169 // Bundle bundle = bundleContext.getBundle();
170 // bundle.stop();
171 // bundle.start();
172 // } catch (BundleException e) {
173 // // TODO Auto-generated catch block
174 // e.printStackTrace();
175 // }
176 }
177
178 private static ResourceLoader createResourceLoader(final String resourceName) {
179 return new ResourceLoader() {
180 public InputStream getResourceAsStream(String resourceName) throws IOException {
181 return getClass().getClassLoader().getResourceAsStream(resourceName);
182 }
183 };
184 }
185
186 public List<String> getResources() {
187 return resources;
188 }
189
190 public AppUi newUi(String name) {
191 if (ui.containsKey(name))
192 throw new IllegalArgumentException("There is already an UI named " + name);
193 AppUi appUi = new AppUi(this);
194 // appUi.setApp(this);
195 ui.put(name, appUi);
196 return appUi;
197 }
198
199 public void addUi(String name, AppUi appUi) {
200 if (ui.containsKey(name))
201 throw new IllegalArgumentException("There is already an UI named " + name);
202 // appUi.setApp(this);
203 ui.put(name, appUi);
204 }
205
206 public void applyBranding(Map<String, String> properties) {
207 if (themeId != null)
208 properties.put(WebClient.THEME_ID, themeId);
209 if (additionalHeaders != null)
210 properties.put(WebClient.HEAD_HTML, additionalHeaders);
211 if (bodyHtml != null)
212 properties.put(WebClient.BODY_HTML, bodyHtml);
213 if (pageTitle != null)
214 properties.put(WebClient.PAGE_TITLE, pageTitle);
215 if (pageOverflow != null)
216 properties.put(WebClient.PAGE_OVERFLOW, pageOverflow);
217 if (favicon != null)
218 properties.put(WebClient.FAVICON, favicon);
219 }
220
221 class CmsExceptionHandler implements ExceptionHandler {
222
223 @Override
224 public void handleException(Throwable throwable) {
225 // TODO be smarter
226 CmsUiUtils.getCmsView().exception(throwable);
227 }
228
229 }
230
231 // public Branding getBranding() {
232 // return branding;
233 // }
234
235 ScriptEngine getScriptEngine() {
236 return scriptEngine;
237 }
238
239 public static String toJson(Node node) {
240 try {
241 StringBuilder sb = new StringBuilder();
242 sb.append('{');
243 PropertyIterator pit = node.getProperties();
244 int count = 0;
245 while (pit.hasNext()) {
246 Property p = pit.nextProperty();
247 int type = p.getType();
248 if (type == PropertyType.REFERENCE || type == PropertyType.WEAKREFERENCE || type == PropertyType.PATH) {
249 Node ref = p.getNode();
250 if (count != 0)
251 sb.append(',');
252 // TODO limit depth?
253 sb.append(toJson(ref));
254 count++;
255 } else if (!p.isMultiple()) {
256 if (count != 0)
257 sb.append(',');
258 sb.append('\"').append(p.getName()).append("\":\"").append(p.getString()).append('\"');
259 count++;
260 }
261 }
262 sb.append('}');
263 return sb.toString();
264 } catch (RepositoryException e) {
265 throw new CmsException("Cannot convert " + node + " to JSON", e);
266 }
267 }
268
269 public void fromJson(Node node, String json) {
270 // TODO
271 }
272
273 public CmsTheme getTheme() {
274 return theme;
275 }
276
277 public void setTheme(CmsTheme theme) {
278 this.theme = theme;
279 }
280
281 public String getWebPath() {
282 return webPath;
283 }
284
285 public void setWebPath(String context) {
286 this.webPath = context;
287 }
288
289 public String getRepo() {
290 return repo;
291 }
292
293 public void setRepo(String repo) {
294 this.repo = repo;
295 }
296
297 public Map<String, AppUi> getUi() {
298 return ui;
299 }
300
301 public void setUi(Map<String, AppUi> ui) {
302 this.ui = ui;
303 }
304
305 // Branding
306 public String getThemeId() {
307 return themeId;
308 }
309
310 public void setThemeId(String themeId) {
311 this.themeId = themeId;
312 }
313
314 public String getAdditionalHeaders() {
315 return additionalHeaders;
316 }
317
318 public void setAdditionalHeaders(String additionalHeaders) {
319 this.additionalHeaders = additionalHeaders;
320 }
321
322 public String getBodyHtml() {
323 return bodyHtml;
324 }
325
326 public void setBodyHtml(String bodyHtml) {
327 this.bodyHtml = bodyHtml;
328 }
329
330 public String getPageTitle() {
331 return pageTitle;
332 }
333
334 public void setPageTitle(String pageTitle) {
335 this.pageTitle = pageTitle;
336 }
337
338 public String getPageOverflow() {
339 return pageOverflow;
340 }
341
342 public void setPageOverflow(String pageOverflow) {
343 this.pageOverflow = pageOverflow;
344 }
345
346 public String getFavicon() {
347 return favicon;
348 }
349
350 public void setFavicon(String favicon) {
351 this.favicon = favicon;
352 }
353
354 public CmsUiProvider getHeader() {
355 return header;
356 }
357
358 public void setHeader(CmsUiProvider header) {
359 this.header = header;
360 }
361
362 public Integer getHeaderHeight() {
363 return headerHeight;
364 }
365
366 public void setHeaderHeight(Integer headerHeight) {
367 this.headerHeight = headerHeight;
368 }
369
370 public CmsUiProvider getLead() {
371 return lead;
372 }
373
374 public void setLead(CmsUiProvider lead) {
375 this.lead = lead;
376 }
377
378 public CmsUiProvider getEnd() {
379 return end;
380 }
381
382 public void setEnd(CmsUiProvider end) {
383 this.end = end;
384 }
385
386 public CmsUiProvider getFooter() {
387 return footer;
388 }
389
390 public void setFooter(CmsUiProvider footer) {
391 this.footer = footer;
392 }
393
394 static class BundleHttpContext implements HttpContext {
395 private BundleContext bundleContext;
396
397 public BundleHttpContext(BundleContext bundleContext) {
398 super();
399 this.bundleContext = bundleContext;
400 }
401
402 @Override
403 public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException {
404 // TODO Auto-generated method stub
405 return true;
406 }
407
408 @Override
409 public URL getResource(String name) {
410
411 return bundleContext.getBundle().getEntry(name);
412 }
413
414 @Override
415 public String getMimeType(String name) {
416 return null;
417 }
418
419 }
420
421 }