X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms.ui.rap%2Fsrc%2Forg%2Fargeo%2Fcms%2Fui%2Fscript%2FCmsScriptApp.java;fp=org.argeo.cms.ui.rap%2Fsrc%2Forg%2Fargeo%2Fcms%2Fui%2Fscript%2FCmsScriptApp.java;h=3f0987199077a0550fcad4f5c74f18b6614f3473;hb=94bd4b03ff3ca9d1875bf6424383d648e604b93a;hp=0000000000000000000000000000000000000000;hpb=0c9de3a0cbb02716f792ebed542b67f0edbe1f4b;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptApp.java b/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptApp.java new file mode 100644 index 000000000..3f0987199 --- /dev/null +++ b/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptApp.java @@ -0,0 +1,422 @@ +package org.argeo.cms.ui.script; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.script.ScriptEngine; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.cms.CmsException; +import org.argeo.cms.ui.CmsConstants; +import org.argeo.cms.ui.CmsTheme; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.cms.web.BundleResourceLoader; +import org.argeo.cms.web.SimpleErgonomics; +import org.argeo.cms.web.WebThemeUtils; +import org.eclipse.rap.rwt.application.Application; +import org.eclipse.rap.rwt.application.Application.OperationMode; +import org.eclipse.rap.rwt.application.ApplicationConfiguration; +import org.eclipse.rap.rwt.application.ExceptionHandler; +import org.eclipse.rap.rwt.client.WebClient; +import org.eclipse.rap.rwt.service.ResourceLoader; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.HttpContext; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.NamespaceException; + +public class CmsScriptApp implements Branding { + public final static String CONTEXT_NAME = "contextName"; + + ServiceRegistration appConfigReg; + + private ScriptEngine scriptEngine; + + private final static Log log = LogFactory.getLog(CmsScriptApp.class); + + private String webPath; + private String repo = "(cn=node)"; + + // private Branding branding = new Branding(); + private CmsTheme theme; + + private List resources = new ArrayList<>(); + + private Map ui = new HashMap<>(); + + private CmsUiProvider header; + private Integer headerHeight = null; + private CmsUiProvider lead; + private CmsUiProvider end; + private CmsUiProvider footer; + + // Branding + private String themeId; + private String additionalHeaders; + private String bodyHtml; + private String pageTitle; + private String pageOverflow; + private String favicon; + + public CmsScriptApp(ScriptEngine scriptEngine) { + super(); + this.scriptEngine = scriptEngine; + } + + public void apply(BundleContext bundleContext, Repository repository, Application application) { + BundleResourceLoader bundleRL = new BundleResourceLoader(bundleContext.getBundle()); + + application.setOperationMode(OperationMode.SWT_COMPATIBILITY); + // application.setOperationMode(OperationMode.JEE_COMPATIBILITY); + + application.setExceptionHandler(new CmsExceptionHandler()); + + // loading animated gif + application.addResource(CmsConstants.LOADING_IMAGE, createResourceLoader(CmsConstants.LOADING_IMAGE)); + // empty image + application.addResource(CmsConstants.NO_IMAGE, createResourceLoader(CmsConstants.NO_IMAGE)); + + for (String resource : resources) { + application.addResource(resource, bundleRL); + if (log.isTraceEnabled()) + log.trace("Resource " + resource); + } + + if (theme != null) { + WebThemeUtils.apply(application, theme); + String themeHeaders = theme.getHtmlHeaders(); + if (themeHeaders != null) { + if (additionalHeaders == null) + additionalHeaders = themeHeaders; + else + additionalHeaders = themeHeaders + "\n" + additionalHeaders; + } + themeId = theme.getThemeId(); + } + + // client JavaScript + Bundle appBundle = bundleRL.getBundle(); + BundleContext bc = appBundle.getBundleContext(); + HttpService httpService = bc.getService(bc.getServiceReference(HttpService.class)); + HttpContext httpContext = new BundleHttpContext(bc); + Enumeration themeResources = appBundle.findEntries("/js/", "*", true); + if (themeResources != null) + bundleResources: while (themeResources.hasMoreElements()) { + try { + String name = themeResources.nextElement().getPath(); + if (name.endsWith("/")) + continue bundleResources; + String alias = "/" + getWebPath() + name; + + httpService.registerResources(alias, name, httpContext); + if (log.isDebugEnabled()) + log.debug("Mapped " + name + " to alias " + alias); + + } catch (NamespaceException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + // App UIs + for (String appUiName : ui.keySet()) { + AppUi appUi = ui.get(appUiName); + appUi.apply(repository, application, this, appUiName); + + } + + } + + public void applySides(SimpleErgonomics simpleErgonomics) { + simpleErgonomics.setHeader(header); + simpleErgonomics.setLead(lead); + simpleErgonomics.setEnd(end); + simpleErgonomics.setFooter(footer); + } + + public void register(BundleContext bundleContext, ApplicationConfiguration appConfig) { + Hashtable props = new Hashtable<>(); + props.put(CONTEXT_NAME, webPath); + appConfigReg = bundleContext.registerService(ApplicationConfiguration.class, appConfig, props); + } + + public void reload() { + BundleContext bundleContext = appConfigReg.getReference().getBundle().getBundleContext(); + ApplicationConfiguration appConfig = bundleContext.getService(appConfigReg.getReference()); + appConfigReg.unregister(); + register(bundleContext, appConfig); + + // BundleContext bundleContext = (BundleContext) + // getScriptEngine().get("bundleContext"); + // try { + // Bundle bundle = bundleContext.getBundle(); + // bundle.stop(); + // bundle.start(); + // } catch (BundleException e) { + // // TODO Auto-generated catch block + // e.printStackTrace(); + // } + } + + private static ResourceLoader createResourceLoader(final String resourceName) { + return new ResourceLoader() { + public InputStream getResourceAsStream(String resourceName) throws IOException { + return getClass().getClassLoader().getResourceAsStream(resourceName); + } + }; + } + + public List getResources() { + return resources; + } + + public AppUi newUi(String name) { + if (ui.containsKey(name)) + throw new IllegalArgumentException("There is already an UI named " + name); + AppUi appUi = new AppUi(this); + // appUi.setApp(this); + ui.put(name, appUi); + return appUi; + } + + public void addUi(String name, AppUi appUi) { + if (ui.containsKey(name)) + throw new IllegalArgumentException("There is already an UI named " + name); + // appUi.setApp(this); + ui.put(name, appUi); + } + + public void applyBranding(Map properties) { + if (themeId != null) + properties.put(WebClient.THEME_ID, themeId); + if (additionalHeaders != null) + properties.put(WebClient.HEAD_HTML, additionalHeaders); + if (bodyHtml != null) + properties.put(WebClient.BODY_HTML, bodyHtml); + if (pageTitle != null) + properties.put(WebClient.PAGE_TITLE, pageTitle); + if (pageOverflow != null) + properties.put(WebClient.PAGE_OVERFLOW, pageOverflow); + if (favicon != null) + properties.put(WebClient.FAVICON, favicon); + } + + class CmsExceptionHandler implements ExceptionHandler { + + @Override + public void handleException(Throwable throwable) { + // TODO be smarter + CmsUiUtils.getCmsView().exception(throwable); + } + + } + + // public Branding getBranding() { + // return branding; + // } + + ScriptEngine getScriptEngine() { + return scriptEngine; + } + + public static String toJson(Node node) { + try { + StringBuilder sb = new StringBuilder(); + sb.append('{'); + PropertyIterator pit = node.getProperties(); + int count = 0; + while (pit.hasNext()) { + Property p = pit.nextProperty(); + int type = p.getType(); + if (type == PropertyType.REFERENCE || type == PropertyType.WEAKREFERENCE || type == PropertyType.PATH) { + Node ref = p.getNode(); + if (count != 0) + sb.append(','); + // TODO limit depth? + sb.append(toJson(ref)); + count++; + } else if (!p.isMultiple()) { + if (count != 0) + sb.append(','); + sb.append('\"').append(p.getName()).append("\":\"").append(p.getString()).append('\"'); + count++; + } + } + sb.append('}'); + return sb.toString(); + } catch (RepositoryException e) { + throw new CmsException("Cannot convert " + node + " to JSON", e); + } + } + + public void fromJson(Node node, String json) { + // TODO + } + + public CmsTheme getTheme() { + return theme; + } + + public void setTheme(CmsTheme theme) { + this.theme = theme; + } + + public String getWebPath() { + return webPath; + } + + public void setWebPath(String context) { + this.webPath = context; + } + + public String getRepo() { + return repo; + } + + public void setRepo(String repo) { + this.repo = repo; + } + + public Map getUi() { + return ui; + } + + public void setUi(Map ui) { + this.ui = ui; + } + + // Branding + public String getThemeId() { + return themeId; + } + + public void setThemeId(String themeId) { + this.themeId = themeId; + } + + public String getAdditionalHeaders() { + return additionalHeaders; + } + + public void setAdditionalHeaders(String additionalHeaders) { + this.additionalHeaders = additionalHeaders; + } + + public String getBodyHtml() { + return bodyHtml; + } + + public void setBodyHtml(String bodyHtml) { + this.bodyHtml = bodyHtml; + } + + public String getPageTitle() { + return pageTitle; + } + + public void setPageTitle(String pageTitle) { + this.pageTitle = pageTitle; + } + + public String getPageOverflow() { + return pageOverflow; + } + + public void setPageOverflow(String pageOverflow) { + this.pageOverflow = pageOverflow; + } + + public String getFavicon() { + return favicon; + } + + public void setFavicon(String favicon) { + this.favicon = favicon; + } + + public CmsUiProvider getHeader() { + return header; + } + + public void setHeader(CmsUiProvider header) { + this.header = header; + } + + public Integer getHeaderHeight() { + return headerHeight; + } + + public void setHeaderHeight(Integer headerHeight) { + this.headerHeight = headerHeight; + } + + public CmsUiProvider getLead() { + return lead; + } + + public void setLead(CmsUiProvider lead) { + this.lead = lead; + } + + public CmsUiProvider getEnd() { + return end; + } + + public void setEnd(CmsUiProvider end) { + this.end = end; + } + + public CmsUiProvider getFooter() { + return footer; + } + + public void setFooter(CmsUiProvider footer) { + this.footer = footer; + } + + static class BundleHttpContext implements HttpContext { + private BundleContext bundleContext; + + public BundleHttpContext(BundleContext bundleContext) { + super(); + this.bundleContext = bundleContext; + } + + @Override + public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException { + // TODO Auto-generated method stub + return true; + } + + @Override + public URL getResource(String name) { + + return bundleContext.getBundle().getEntry(name); + } + + @Override + public String getMimeType(String name) { + return null; + } + + } + +}